build: cleanup src/rtos directory
Change-Id: I24bc62d12409dbfc20a0a986acf6b3f2c913e36d Signed-off-by: Spencer Oliver <spen@spen-soft.co.uk> Reviewed-on: http://openocd.zylin.com/416 Tested-by: jenkins__archive__
parent
8b00e56e64
commit
7b032df3aa
|
@ -18,7 +18,6 @@
|
||||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,370 +30,346 @@
|
||||||
#include "helper/log.h"
|
#include "helper/log.h"
|
||||||
#include "rtos_standard_stackings.h"
|
#include "rtos_standard_stackings.h"
|
||||||
|
|
||||||
#define FreeRTOS_STRUCT( int_type, ptr_type, list_prev_offset )
|
#define FreeRTOS_STRUCT(int_type, ptr_type, list_prev_offset)
|
||||||
|
|
||||||
|
struct FreeRTOS_params {
|
||||||
struct FreeRTOS_params
|
const char *target_name;
|
||||||
{
|
const unsigned char thread_count_width;
|
||||||
const char * target_name;
|
const unsigned char pointer_width;
|
||||||
const unsigned char thread_count_width;
|
const unsigned char list_next_offset;
|
||||||
const unsigned char pointer_width;
|
const unsigned char list_width;
|
||||||
const unsigned char list_next_offset;
|
const unsigned char list_elem_next_offset;
|
||||||
const unsigned char list_width;
|
const unsigned char list_elem_content_offset;
|
||||||
const unsigned char list_elem_next_offset;
|
const unsigned char thread_stack_offset;
|
||||||
const unsigned char list_elem_content_offset;
|
const unsigned char thread_name_offset;
|
||||||
const unsigned char thread_stack_offset;
|
const struct rtos_register_stacking *stacking_info;
|
||||||
const unsigned char thread_name_offset;
|
|
||||||
const struct rtos_register_stacking* stacking_info;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const struct FreeRTOS_params FreeRTOS_params_list[] = {
|
||||||
|
{
|
||||||
|
"cortex_m3", /* target_name */
|
||||||
const struct FreeRTOS_params FreeRTOS_params_list[] =
|
4, /* thread_count_width; */
|
||||||
{
|
4, /* pointer_width; */
|
||||||
{ "cortex_m3", // target_name
|
16, /* list_next_offset; */
|
||||||
4, // thread_count_width;
|
20, /* list_width; */
|
||||||
4, // pointer_width;
|
8, /* list_elem_next_offset; */
|
||||||
16, // list_next_offset;
|
12, /* list_elem_content_offset */
|
||||||
20, // list_width;
|
0, /* thread_stack_offset; */
|
||||||
8, // list_elem_next_offset;
|
52, /* thread_name_offset; */
|
||||||
12, // list_elem_content_offset
|
&rtos_standard_Cortex_M3_stacking, /* stacking_info */
|
||||||
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)))
|
#define FREERTOS_NUM_PARAMS ((int)(sizeof(FreeRTOS_params_list)/sizeof(struct FreeRTOS_params)))
|
||||||
|
|
||||||
static int FreeRTOS_detect_rtos( struct target* target );
|
static int FreeRTOS_detect_rtos(struct target *target);
|
||||||
static int FreeRTOS_create( struct target* target );
|
static int FreeRTOS_create(struct target *target);
|
||||||
static int FreeRTOS_update_threads( struct rtos *rtos );
|
static int FreeRTOS_update_threads(struct rtos *rtos);
|
||||||
static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char ** hex_reg_list );
|
static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list);
|
||||||
static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t * symbol_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,
|
||||||
struct rtos_type FreeRTOS_rtos =
|
.update_threads = FreeRTOS_update_threads,
|
||||||
{
|
.get_thread_reg_list = FreeRTOS_get_thread_reg_list,
|
||||||
.name = "FreeRTOS",
|
.get_symbol_list_to_lookup = FreeRTOS_get_symbol_list_to_lookup,
|
||||||
|
|
||||||
.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
|
enum FreeRTOS_symbol_values {
|
||||||
{
|
FreeRTOS_VAL_pxCurrentTCB = 0,
|
||||||
FreeRTOS_VAL_pxCurrentTCB = 0,
|
FreeRTOS_VAL_pxReadyTasksLists = 1,
|
||||||
FreeRTOS_VAL_pxReadyTasksLists = 1,
|
FreeRTOS_VAL_xDelayedTaskList1 = 2,
|
||||||
FreeRTOS_VAL_xDelayedTaskList1 = 2,
|
FreeRTOS_VAL_xDelayedTaskList2 = 3,
|
||||||
FreeRTOS_VAL_xDelayedTaskList2 = 3,
|
FreeRTOS_VAL_pxDelayedTaskList = 4,
|
||||||
FreeRTOS_VAL_pxDelayedTaskList = 4,
|
|
||||||
FreeRTOS_VAL_pxOverflowDelayedTaskList = 5,
|
FreeRTOS_VAL_pxOverflowDelayedTaskList = 5,
|
||||||
FreeRTOS_VAL_xPendingReadyList = 6,
|
FreeRTOS_VAL_xPendingReadyList = 6,
|
||||||
FreeRTOS_VAL_xTasksWaitingTermination = 7,
|
FreeRTOS_VAL_xTasksWaitingTermination = 7,
|
||||||
FreeRTOS_VAL_xSuspendedTaskList = 8,
|
FreeRTOS_VAL_xSuspendedTaskList = 8,
|
||||||
FreeRTOS_VAL_uxCurrentNumberOfTasks = 9,
|
FreeRTOS_VAL_uxCurrentNumberOfTasks = 9,
|
||||||
FreeRTOS_VAL_uxTopUsedPriority = 10,
|
FreeRTOS_VAL_uxTopUsedPriority = 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
static char* FreeRTOS_symbol_list[] =
|
static char *FreeRTOS_symbol_list[] = {
|
||||||
{
|
"pxCurrentTCB",
|
||||||
"pxCurrentTCB",
|
"pxReadyTasksLists",
|
||||||
"pxReadyTasksLists",
|
"xDelayedTaskList1",
|
||||||
"xDelayedTaskList1",
|
"xDelayedTaskList2",
|
||||||
"xDelayedTaskList2",
|
"pxDelayedTaskList",
|
||||||
"pxDelayedTaskList",
|
"pxOverflowDelayedTaskList",
|
||||||
"pxOverflowDelayedTaskList",
|
"xPendingReadyList",
|
||||||
"xPendingReadyList",
|
"xTasksWaitingTermination",
|
||||||
"xTasksWaitingTermination",
|
"xSuspendedTaskList",
|
||||||
"xSuspendedTaskList",
|
"uxCurrentNumberOfTasks",
|
||||||
"uxCurrentNumberOfTasks",
|
"uxTopUsedPriority",
|
||||||
"uxTopUsedPriority",
|
NULL
|
||||||
NULL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FREERTOS_NUM_SYMBOLS (sizeof(FreeRTOS_symbol_list)/sizeof(char*))
|
#define FREERTOS_NUM_SYMBOLS (sizeof(FreeRTOS_symbol_list)/sizeof(char *))
|
||||||
|
|
||||||
// TODO:
|
/* TODO: */
|
||||||
// this is not safe for little endian yet
|
/* this is not safe for little endian yet */
|
||||||
// may be problems reading if sizes are not 32 bit long integers.
|
/* may be problems reading if sizes are not 32 bit long integers. */
|
||||||
// test mallocs for failure
|
/* test mallocs for failure */
|
||||||
|
|
||||||
static int FreeRTOS_update_threads( struct rtos *rtos )
|
static int FreeRTOS_update_threads(struct rtos *rtos)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int retval;
|
int retval;
|
||||||
int tasks_found = 0;
|
int tasks_found = 0;
|
||||||
const struct FreeRTOS_params* param;
|
const struct FreeRTOS_params *param;
|
||||||
|
|
||||||
if (rtos->rtos_specific_params == NULL )
|
if (rtos->rtos_specific_params == NULL)
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
param = (const struct FreeRTOS_params*) rtos->rtos_specific_params;
|
param = (const struct FreeRTOS_params *) rtos->rtos_specific_params;
|
||||||
|
|
||||||
if ( rtos->symbols == NULL )
|
if (rtos->symbols == NULL) {
|
||||||
{
|
|
||||||
LOG_OUTPUT("No symbols for FreeRTOS\r\n");
|
LOG_OUTPUT("No symbols for FreeRTOS\r\n");
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( rtos->symbols[FreeRTOS_VAL_uxCurrentNumberOfTasks].address == 0 )
|
if (rtos->symbols[FreeRTOS_VAL_uxCurrentNumberOfTasks].address == 0) {
|
||||||
{
|
|
||||||
LOG_OUTPUT("Don't have the number of threads in FreeRTOS \r\n");
|
LOG_OUTPUT("Don't have the number of threads in FreeRTOS \r\n");
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int thread_list_size = 0;
|
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);
|
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 )
|
if (retval != ERROR_OK) {
|
||||||
{
|
|
||||||
LOG_OUTPUT("Could not read FreeRTOS thread count from target\r\n");
|
LOG_OUTPUT("Could not read FreeRTOS thread count from target\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* wipe out previous thread details if any */
|
||||||
// wipe out previous thread details if any
|
if (rtos->thread_details != NULL) {
|
||||||
if ( rtos->thread_details != NULL )
|
|
||||||
{
|
|
||||||
int j;
|
int j;
|
||||||
for( j = 0; j < rtos->thread_count; j++ )
|
for (j = 0; j < rtos->thread_count; j++) {
|
||||||
{
|
if (rtos->thread_details[j].display_str != NULL) {
|
||||||
if ( rtos->thread_details[j].display_str != NULL )
|
free(rtos->thread_details[j].display_str);
|
||||||
{
|
|
||||||
free( rtos->thread_details[j].display_str );
|
|
||||||
rtos->thread_details[j].display_str = NULL;
|
rtos->thread_details[j].display_str = NULL;
|
||||||
}
|
}
|
||||||
if ( rtos->thread_details[j].thread_name_str != NULL )
|
if (rtos->thread_details[j].thread_name_str != NULL) {
|
||||||
{
|
free(rtos->thread_details[j].thread_name_str);
|
||||||
free( rtos->thread_details[j].thread_name_str );
|
|
||||||
rtos->thread_details[j].thread_name_str = NULL;
|
rtos->thread_details[j].thread_name_str = NULL;
|
||||||
}
|
}
|
||||||
if ( rtos->thread_details[j].extra_info_str != NULL )
|
if (rtos->thread_details[j].extra_info_str != NULL) {
|
||||||
{
|
free(rtos->thread_details[j].extra_info_str);
|
||||||
free( rtos->thread_details[j].extra_info_str );
|
|
||||||
rtos->thread_details[j].extra_info_str = NULL;
|
rtos->thread_details[j].extra_info_str = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free( rtos->thread_details );
|
free(rtos->thread_details);
|
||||||
rtos->thread_details = NULL;
|
rtos->thread_details = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* read the current thread */
|
||||||
// read the current thread
|
retval = target_read_buffer(rtos->target,
|
||||||
retval = target_read_buffer( rtos->target, rtos->symbols[FreeRTOS_VAL_pxCurrentTCB].address, param->pointer_width, (uint8_t *)&rtos->current_thread );
|
rtos->symbols[FreeRTOS_VAL_pxCurrentTCB].address,
|
||||||
if ( retval != ERROR_OK )
|
param->pointer_width,
|
||||||
{
|
(uint8_t *)&rtos->current_thread);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
LOG_OUTPUT("Error reading current thread in FreeRTOS thread list\r\n");
|
LOG_OUTPUT("Error reading current thread in FreeRTOS thread list\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ( thread_list_size == 0 ) || ( rtos->current_thread == 0 ) )
|
if ((thread_list_size == 0) || (rtos->current_thread == 0)) {
|
||||||
{
|
/* Either : No RTOS threads - there is always at least the current execution though */
|
||||||
// Either : No RTOS threads - there is always at least the current execution though
|
/* OR : No current thread - all threads suspended - show the current execution
|
||||||
// OR : No current thread - all threads suspended - show the current execution of idling
|
* of idling */
|
||||||
char tmp_str[] = "Current Execution";
|
char tmp_str[] = "Current Execution";
|
||||||
thread_list_size++;
|
thread_list_size++;
|
||||||
tasks_found++;
|
tasks_found++;
|
||||||
rtos->thread_details = (struct thread_detail*) malloc( sizeof( struct thread_detail ) * thread_list_size );
|
rtos->thread_details = (struct thread_detail *) malloc(
|
||||||
|
sizeof(struct thread_detail) * thread_list_size);
|
||||||
rtos->thread_details->threadid = 1;
|
rtos->thread_details->threadid = 1;
|
||||||
rtos->thread_details->exists = true;
|
rtos->thread_details->exists = true;
|
||||||
rtos->thread_details->display_str = NULL;
|
rtos->thread_details->display_str = NULL;
|
||||||
rtos->thread_details->extra_info_str = NULL;
|
rtos->thread_details->extra_info_str = NULL;
|
||||||
rtos->thread_details->thread_name_str = (char*) malloc( sizeof(tmp_str) );
|
rtos->thread_details->thread_name_str = (char *) malloc(sizeof(tmp_str));
|
||||||
strcpy( rtos->thread_details->thread_name_str, tmp_str );
|
strcpy(rtos->thread_details->thread_name_str, tmp_str);
|
||||||
|
|
||||||
|
if (thread_list_size == 1) {
|
||||||
if ( thread_list_size == 1 )
|
|
||||||
{
|
|
||||||
rtos->thread_count = 1;
|
rtos->thread_count = 1;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
/* create space for new thread details */
|
||||||
{
|
rtos->thread_details = (struct thread_detail *) malloc(
|
||||||
// create space for new thread details
|
sizeof(struct thread_detail) * thread_list_size);
|
||||||
rtos->thread_details = (struct thread_detail*) malloc( sizeof( struct thread_detail ) * thread_list_size );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Find out how many lists are needed to be read from pxReadyTasksLists, */
|
||||||
// Find out how many lists are needed to be read from pxReadyTasksLists,
|
|
||||||
int64_t max_used_priority = 0;
|
int64_t max_used_priority = 0;
|
||||||
retval = target_read_buffer( rtos->target, rtos->symbols[FreeRTOS_VAL_uxTopUsedPriority].address, param->pointer_width, (uint8_t *)&max_used_priority );
|
retval = target_read_buffer(rtos->target,
|
||||||
|
rtos->symbols[FreeRTOS_VAL_uxTopUsedPriority].address,
|
||||||
|
param->pointer_width,
|
||||||
|
(uint8_t *)&max_used_priority);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
symbol_address_t* list_of_lists = (symbol_address_t *)malloc( sizeof( symbol_address_t ) * ( max_used_priority+1 + 5 ) );
|
symbol_address_t *list_of_lists =
|
||||||
|
(symbol_address_t *)malloc(sizeof(symbol_address_t) *
|
||||||
|
(max_used_priority+1 + 5));
|
||||||
|
|
||||||
int num_lists;
|
int num_lists;
|
||||||
for( num_lists = 0; num_lists <= max_used_priority; num_lists++ )
|
for (num_lists = 0; num_lists <= max_used_priority; num_lists++)
|
||||||
{
|
list_of_lists[num_lists] = rtos->symbols[FreeRTOS_VAL_pxReadyTasksLists].address +
|
||||||
list_of_lists[num_lists] = rtos->symbols[FreeRTOS_VAL_pxReadyTasksLists].address + num_lists * param->list_width;
|
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_xDelayedTaskList1].address;
|
||||||
list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xDelayedTaskList2].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_xPendingReadyList].address;
|
||||||
list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xSuspendedTaskList].address;
|
list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xSuspendedTaskList].address;
|
||||||
list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xTasksWaitingTermination].address;
|
list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xTasksWaitingTermination].address;
|
||||||
|
|
||||||
|
for (i = 0; i < num_lists; i++) {
|
||||||
for( i = 0; i < num_lists; i++ )
|
if (list_of_lists[i] == 0)
|
||||||
{
|
|
||||||
if ( list_of_lists[i] == 0 )
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
// Read the number of threads in this list
|
/* Read the number of threads in this list */
|
||||||
int64_t list_thread_count = 0;
|
int64_t list_thread_count = 0;
|
||||||
retval = target_read_buffer( rtos->target, list_of_lists[i], param->thread_count_width, (uint8_t *)&list_thread_count);
|
retval = target_read_buffer(rtos->target,
|
||||||
if ( retval != ERROR_OK )
|
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");
|
LOG_OUTPUT("Error reading number of threads in FreeRTOS thread list\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( list_thread_count == 0 )
|
if (list_thread_count == 0)
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
// Read the location of first list item
|
/* Read the location of first list item */
|
||||||
uint64_t prev_list_elem_ptr = -1;
|
uint64_t prev_list_elem_ptr = -1;
|
||||||
uint64_t list_elem_ptr = 0;
|
uint64_t 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);
|
retval = target_read_buffer(rtos->target,
|
||||||
if ( retval != ERROR_OK )
|
list_of_lists[i] + param->list_next_offset,
|
||||||
{
|
param->pointer_width,
|
||||||
LOG_OUTPUT("Error reading first thread item location in FreeRTOS thread list\r\n");
|
(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;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while ((list_thread_count > 0) && (list_elem_ptr != 0) &&
|
||||||
while ( (list_thread_count > 0) && ( list_elem_ptr != 0) && ( list_elem_ptr != prev_list_elem_ptr ) && ( tasks_found < thread_list_size ) )
|
(list_elem_ptr != prev_list_elem_ptr) &&
|
||||||
{
|
(tasks_found < thread_list_size)) {
|
||||||
// Get the location of the thread structure.
|
/* Get the location of the thread structure. */
|
||||||
rtos->thread_details[tasks_found].threadid = 0;
|
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));
|
retval = target_read_buffer(rtos->target,
|
||||||
if ( retval != ERROR_OK )
|
list_elem_ptr + param->list_elem_content_offset,
|
||||||
{
|
param->pointer_width,
|
||||||
LOG_OUTPUT("Error reading thread list item object in FreeRTOS thread list\r\n");
|
(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;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* get thread name */
|
||||||
// get thread name
|
|
||||||
|
|
||||||
#define FREERTOS_THREAD_NAME_STR_SIZE (200)
|
#define FREERTOS_THREAD_NAME_STR_SIZE (200)
|
||||||
char tmp_str[FREERTOS_THREAD_NAME_STR_SIZE];
|
char tmp_str[FREERTOS_THREAD_NAME_STR_SIZE];
|
||||||
|
|
||||||
// Read the thread name
|
/* 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);
|
retval = target_read_buffer(rtos->target,
|
||||||
if ( retval != ERROR_OK )
|
rtos->thread_details[tasks_found].threadid + param->thread_name_offset,
|
||||||
{
|
FREERTOS_THREAD_NAME_STR_SIZE,
|
||||||
LOG_OUTPUT("Error reading first thread item location in FreeRTOS thread list\r\n");
|
(uint8_t *)&tmp_str);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
|
LOG_OUTPUT(
|
||||||
|
"Error reading first thread item location in FreeRTOS thread list\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
tmp_str[FREERTOS_THREAD_NAME_STR_SIZE-1] = '\x00';
|
tmp_str[FREERTOS_THREAD_NAME_STR_SIZE-1] = '\x00';
|
||||||
|
|
||||||
if ( tmp_str[0] == '\x00' )
|
if (tmp_str[0] == '\x00')
|
||||||
{
|
strcpy(tmp_str, "No Name");
|
||||||
strcpy(tmp_str,"No Name");
|
|
||||||
}
|
|
||||||
|
|
||||||
rtos->thread_details[tasks_found].thread_name_str = (char*)malloc( strlen(tmp_str)+1 );
|
rtos->thread_details[tasks_found].thread_name_str =
|
||||||
strcpy( rtos->thread_details[tasks_found].thread_name_str, tmp_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].display_str = NULL;
|
||||||
rtos->thread_details[tasks_found].exists = true;
|
rtos->thread_details[tasks_found].exists = true;
|
||||||
|
|
||||||
if ( rtos->thread_details[tasks_found].threadid == rtos->current_thread )
|
if (rtos->thread_details[tasks_found].threadid == rtos->current_thread) {
|
||||||
{
|
|
||||||
char running_str[] = "Running";
|
char running_str[] = "Running";
|
||||||
rtos->thread_details[tasks_found].extra_info_str = (char*) malloc( sizeof(running_str) );
|
rtos->thread_details[tasks_found].extra_info_str = (char *) malloc(
|
||||||
strcpy( rtos->thread_details[tasks_found].extra_info_str, running_str );
|
sizeof(running_str));
|
||||||
}
|
strcpy(rtos->thread_details[tasks_found].extra_info_str,
|
||||||
else
|
running_str);
|
||||||
{
|
} else
|
||||||
rtos->thread_details[tasks_found].extra_info_str = NULL;
|
rtos->thread_details[tasks_found].extra_info_str = NULL;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
tasks_found++;
|
tasks_found++;
|
||||||
list_thread_count--;
|
list_thread_count--;
|
||||||
|
|
||||||
prev_list_elem_ptr = list_elem_ptr;
|
prev_list_elem_ptr = list_elem_ptr;
|
||||||
list_elem_ptr = 0;
|
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);
|
retval = target_read_buffer(rtos->target,
|
||||||
if ( retval != ERROR_OK )
|
prev_list_elem_ptr + param->list_elem_next_offset,
|
||||||
{
|
param->pointer_width,
|
||||||
LOG_OUTPUT("Error reading next thread item location in FreeRTOS thread list\r\n");
|
(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;
|
return retval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
free( list_of_lists );
|
free(list_of_lists);
|
||||||
rtos->thread_count = tasks_found;
|
rtos->thread_count = tasks_found;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char ** hex_reg_list )
|
static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
const struct FreeRTOS_params* param;
|
const struct FreeRTOS_params *param;
|
||||||
int64_t stack_ptr = 0;
|
int64_t stack_ptr = 0;
|
||||||
|
|
||||||
|
|
||||||
*hex_reg_list = NULL;
|
*hex_reg_list = NULL;
|
||||||
if ( rtos == NULL )
|
if (rtos == NULL)
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
if ( thread_id == 0 )
|
if (thread_id == 0)
|
||||||
{
|
|
||||||
return -2;
|
return -2;
|
||||||
}
|
|
||||||
|
|
||||||
if (rtos->rtos_specific_params == NULL )
|
if (rtos->rtos_specific_params == NULL)
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
param = (const struct FreeRTOS_params*) rtos->rtos_specific_params;
|
param = (const struct FreeRTOS_params *) rtos->rtos_specific_params;
|
||||||
|
|
||||||
// Read the stack pointer
|
/* Read the stack pointer */
|
||||||
retval = target_read_buffer( rtos->target, thread_id + param->thread_stack_offset, param->pointer_width, (uint8_t*)&stack_ptr);
|
retval = target_read_buffer(rtos->target,
|
||||||
if ( retval != ERROR_OK )
|
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");
|
LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rtos_generic_stack_read( rtos->target, param->stacking_info, stack_ptr, hex_reg_list );
|
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[])
|
static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
*symbol_list = (symbol_table_elem_t *) malloc( sizeof( symbol_table_elem_t ) * FREERTOS_NUM_SYMBOLS );
|
*symbol_list = (symbol_table_elem_t *) malloc(
|
||||||
|
sizeof(symbol_table_elem_t) * FREERTOS_NUM_SYMBOLS);
|
||||||
|
|
||||||
for( i = 0; i < FREERTOS_NUM_SYMBOLS; i++ )
|
for (i = 0; i < FREERTOS_NUM_SYMBOLS; i++)
|
||||||
{
|
|
||||||
(*symbol_list)[i].symbol_name = FreeRTOS_symbol_list[i];
|
(*symbol_list)[i].symbol_name = FreeRTOS_symbol_list[i];
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -406,81 +381,68 @@ static int FreeRTOS_set_current_thread(struct rtos *rtos, threadid_t thread_id)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int FreeRTOS_get_thread_ascii_info(struct rtos *rtos, threadid_t thread_id, char **info)
|
||||||
|
|
||||||
static int FreeRTOS_get_thread_ascii_info( struct rtos* rtos, threadid_t thread_id, char ** info )
|
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
const struct FreeRTOS_params* param;
|
const struct FreeRTOS_params *param;
|
||||||
|
|
||||||
if ( rtos == NULL )
|
if (rtos == NULL)
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
if ( thread_id == 0 )
|
if (thread_id == 0)
|
||||||
{
|
|
||||||
return -2;
|
return -2;
|
||||||
}
|
|
||||||
|
|
||||||
if (rtos->rtos_specific_params == NULL )
|
if (rtos->rtos_specific_params == NULL)
|
||||||
{
|
|
||||||
return -3;
|
return -3;
|
||||||
}
|
|
||||||
|
|
||||||
param = (const struct FreeRTOS_params*) rtos->rtos_specific_params;
|
param = (const struct FreeRTOS_params *) rtos->rtos_specific_params;
|
||||||
|
|
||||||
#define FREERTOS_THREAD_NAME_STR_SIZE (200)
|
#define FREERTOS_THREAD_NAME_STR_SIZE (200)
|
||||||
char tmp_str[FREERTOS_THREAD_NAME_STR_SIZE];
|
char tmp_str[FREERTOS_THREAD_NAME_STR_SIZE];
|
||||||
|
|
||||||
// Read the thread name
|
/* 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);
|
retval = target_read_buffer(rtos->target,
|
||||||
if ( retval != ERROR_OK )
|
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");
|
LOG_OUTPUT("Error reading first thread item location in FreeRTOS thread list\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
tmp_str[FREERTOS_THREAD_NAME_STR_SIZE-1] = '\x00';
|
tmp_str[FREERTOS_THREAD_NAME_STR_SIZE-1] = '\x00';
|
||||||
|
|
||||||
if ( tmp_str[0] == '\x00' )
|
if (tmp_str[0] == '\x00')
|
||||||
{
|
strcpy(tmp_str, "No Name");
|
||||||
strcpy(tmp_str,"No Name");
|
|
||||||
}
|
|
||||||
|
|
||||||
*info = (char*)malloc( strlen(tmp_str)+1 );
|
*info = (char *)malloc(strlen(tmp_str)+1);
|
||||||
strcpy( *info, tmp_str );
|
strcpy(*info, tmp_str);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int FreeRTOS_detect_rtos( struct target* target )
|
static int FreeRTOS_detect_rtos(struct target *target)
|
||||||
{
|
{
|
||||||
if ( ( target->rtos->symbols != NULL ) &&
|
if ((target->rtos->symbols != NULL) &&
|
||||||
( target->rtos->symbols[FreeRTOS_VAL_pxReadyTasksLists].address != 0 ) )
|
(target->rtos->symbols[FreeRTOS_VAL_pxReadyTasksLists].address != 0)) {
|
||||||
{
|
/* looks like FreeRTOS */
|
||||||
// looks like FreeRTOS
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int FreeRTOS_create(struct target *target)
|
||||||
static int FreeRTOS_create( struct target* target )
|
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while ( ( i < FREERTOS_NUM_PARAMS ) && ( 0 != strcmp( FreeRTOS_params_list[i].target_name, target->type->name ) ) )
|
while ((i < FREERTOS_NUM_PARAMS) &&
|
||||||
{
|
(0 != strcmp(FreeRTOS_params_list[i].target_name, target->type->name))) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if ( i >= FREERTOS_NUM_PARAMS )
|
if (i >= FREERTOS_NUM_PARAMS) {
|
||||||
{
|
|
||||||
LOG_OUTPUT("Could not find target in FreeRTOS compatibility list\r\n");
|
LOG_OUTPUT("Could not find target in FreeRTOS compatibility list\r\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
target->rtos->rtos_specific_params = (void*) &FreeRTOS_params_list[i];
|
target->rtos->rtos_specific_params = (void *) &FreeRTOS_params_list[i];
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,312 +30,275 @@
|
||||||
#include "helper/log.h"
|
#include "helper/log.h"
|
||||||
#include "rtos_standard_stackings.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, int64_t thread_id, char **hex_reg_list);
|
||||||
|
static int ThreadX_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]);
|
||||||
|
|
||||||
static int ThreadX_detect_rtos( struct target* target );
|
struct ThreadX_thread_state {
|
||||||
static int ThreadX_create( struct target* target );
|
|
||||||
static int ThreadX_update_threads( struct rtos* rtos);
|
|
||||||
static int ThreadX_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char ** hex_reg_list );
|
|
||||||
static int ThreadX_get_symbol_list_to_lookup(symbol_table_elem_t * symbol_list[]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct ThreadX_thread_state
|
|
||||||
{
|
|
||||||
int value;
|
int value;
|
||||||
char * desc;
|
char *desc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ThreadX_thread_state ThreadX_thread_states[] = {
|
||||||
struct ThreadX_thread_state ThreadX_thread_states[] =
|
{ 0, "Ready" },
|
||||||
{
|
{ 1, "Completed" },
|
||||||
{ 0, "Ready" },
|
{ 2, "Terminated" },
|
||||||
{ 1, "Completed" },
|
{ 3, "Suspended" },
|
||||||
{ 2, "Terminated" },
|
{ 4, "Sleeping" },
|
||||||
{ 3, "Suspended" },
|
{ 5, "Waiting - Queue" },
|
||||||
{ 4, "Sleeping" },
|
{ 6, "Waiting - Semaphore" },
|
||||||
{ 5, "Waiting - Queue" },
|
{ 7, "Waiting - Event flag" },
|
||||||
{ 6, "Waiting - Semaphore" },
|
{ 8, "Waiting - Memory" },
|
||||||
{ 7, "Waiting - Event flag" },
|
{ 9, "Waiting - Memory" },
|
||||||
{ 8, "Waiting - Memory" },
|
{ 10, "Waiting - I/O" },
|
||||||
{ 9, "Waiting - Memory" },
|
{ 11, "Waiting - Filesystem" },
|
||||||
{ 10, "Waiting - I/O" },
|
{ 12, "Waiting - Network" },
|
||||||
{ 11, "Waiting - Filesystem" },
|
{ 13, "Waiting - Mutex" },
|
||||||
{ 12, "Waiting - Network" },
|
|
||||||
{ 13, "Waiting - Mutex" },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#define THREADX_NUM_STATES (sizeof(ThreadX_thread_states)/sizeof(struct ThreadX_thread_state))
|
#define THREADX_NUM_STATES (sizeof(ThreadX_thread_states)/sizeof(struct ThreadX_thread_state))
|
||||||
|
|
||||||
|
struct ThreadX_params {
|
||||||
struct ThreadX_params
|
char *target_name;
|
||||||
{
|
unsigned char pointer_width;
|
||||||
char * target_name;
|
unsigned char thread_stack_offset;
|
||||||
unsigned char pointer_width;
|
unsigned char thread_name_offset;
|
||||||
unsigned char thread_stack_offset;
|
unsigned char thread_state_offset;
|
||||||
unsigned char thread_name_offset;
|
unsigned char thread_next_offset;
|
||||||
unsigned char thread_state_offset;
|
const struct rtos_register_stacking *stacking_info;
|
||||||
unsigned char thread_next_offset;
|
|
||||||
const struct rtos_register_stacking* stacking_info;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct ThreadX_params ThreadX_params_list[] =
|
const struct ThreadX_params ThreadX_params_list[] = {
|
||||||
{
|
{
|
||||||
{ "cortex_m3", // target_name
|
"cortex_m3", /* target_name */
|
||||||
4, // pointer_width;
|
4, /* pointer_width; */
|
||||||
8, // thread_stack_offset;
|
8, /* thread_stack_offset; */
|
||||||
40, // thread_name_offset;
|
40, /* thread_name_offset; */
|
||||||
48, // thread_state_offset;
|
48, /* thread_state_offset; */
|
||||||
136, // thread_next_offset
|
136, /* thread_next_offset */
|
||||||
&rtos_standard_Cortex_M3_stacking, // stacking_info
|
&rtos_standard_Cortex_M3_stacking, /* stacking_info */
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define THREADX_NUM_PARAMS ((int)(sizeof(ThreadX_params_list)/sizeof(struct ThreadX_params)))
|
#define THREADX_NUM_PARAMS ((int)(sizeof(ThreadX_params_list)/sizeof(struct ThreadX_params)))
|
||||||
|
|
||||||
enum ThreadX_symbol_values
|
enum ThreadX_symbol_values {
|
||||||
{
|
ThreadX_VAL_tx_thread_current_ptr = 0,
|
||||||
ThreadX_VAL_tx_thread_current_ptr = 0,
|
ThreadX_VAL_tx_thread_created_ptr = 1,
|
||||||
ThreadX_VAL_tx_thread_created_ptr = 1,
|
ThreadX_VAL_tx_thread_created_count = 2,
|
||||||
ThreadX_VAL_tx_thread_created_count = 2,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static char* ThreadX_symbol_list[] =
|
static char *ThreadX_symbol_list[] = {
|
||||||
{
|
"_tx_thread_current_ptr",
|
||||||
"_tx_thread_current_ptr",
|
"_tx_thread_created_ptr",
|
||||||
"_tx_thread_created_ptr",
|
"_tx_thread_created_count",
|
||||||
"_tx_thread_created_count",
|
NULL
|
||||||
NULL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define THREADX_NUM_SYMBOLS (sizeof(ThreadX_symbol_list)/sizeof(char *))
|
||||||
|
|
||||||
|
const struct rtos_type ThreadX_rtos = {
|
||||||
|
.name = "ThreadX",
|
||||||
|
|
||||||
#define THREADX_NUM_SYMBOLS (sizeof(ThreadX_symbol_list)/sizeof(char*))
|
.detect_rtos = ThreadX_detect_rtos,
|
||||||
|
.create = ThreadX_create,
|
||||||
|
.update_threads = ThreadX_update_threads,
|
||||||
const struct rtos_type ThreadX_rtos =
|
.get_thread_reg_list = ThreadX_get_thread_reg_list,
|
||||||
{
|
|
||||||
.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,
|
.get_symbol_list_to_lookup = ThreadX_get_symbol_list_to_lookup,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ThreadX_update_threads( struct rtos* rtos)
|
static int ThreadX_update_threads(struct rtos *rtos)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
int tasks_found = 0;
|
int tasks_found = 0;
|
||||||
int thread_list_size = 0;
|
int thread_list_size = 0;
|
||||||
const struct ThreadX_params* param;
|
const struct ThreadX_params *param;
|
||||||
|
|
||||||
if ( rtos == NULL )
|
if (rtos == NULL)
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
if (rtos->rtos_specific_params == NULL )
|
if (rtos->rtos_specific_params == NULL)
|
||||||
{
|
|
||||||
return -3;
|
return -3;
|
||||||
}
|
|
||||||
|
|
||||||
param = (const struct ThreadX_params*) rtos->rtos_specific_params;
|
param = (const struct ThreadX_params *) rtos->rtos_specific_params;
|
||||||
|
|
||||||
if ( rtos->symbols == NULL )
|
if (rtos->symbols == NULL) {
|
||||||
{
|
|
||||||
LOG_OUTPUT("No symbols for ThreadX\r\n");
|
LOG_OUTPUT("No symbols for ThreadX\r\n");
|
||||||
return -4;
|
return -4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( rtos->symbols[ThreadX_VAL_tx_thread_created_count].address == 0 )
|
if (rtos->symbols[ThreadX_VAL_tx_thread_created_count].address == 0) {
|
||||||
{
|
|
||||||
LOG_OUTPUT("Don't have the number of threads in ThreadX \r\n");
|
LOG_OUTPUT("Don't have the number of threads in ThreadX \r\n");
|
||||||
return -2;
|
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) {
|
||||||
|
|
||||||
|
|
||||||
// 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");
|
LOG_OUTPUT("Could not read ThreadX thread count from target\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* wipe out previous thread details if any */
|
||||||
// wipe out previous thread details if any
|
if (rtos->thread_details != NULL) {
|
||||||
if ( rtos->thread_details != NULL )
|
|
||||||
{
|
|
||||||
int j;
|
int j;
|
||||||
for( j = 0; j < rtos->thread_count; j++ )
|
for (j = 0; j < rtos->thread_count; j++) {
|
||||||
{
|
if (rtos->thread_details[j].display_str != NULL) {
|
||||||
if ( rtos->thread_details[j].display_str != NULL )
|
free(rtos->thread_details[j].display_str);
|
||||||
{
|
|
||||||
free( rtos->thread_details[j].display_str );
|
|
||||||
rtos->thread_details[j].display_str = NULL;
|
rtos->thread_details[j].display_str = NULL;
|
||||||
}
|
}
|
||||||
if ( rtos->thread_details[j].thread_name_str != NULL )
|
if (rtos->thread_details[j].thread_name_str != NULL) {
|
||||||
{
|
free(rtos->thread_details[j].thread_name_str);
|
||||||
free( rtos->thread_details[j].thread_name_str );
|
|
||||||
rtos->thread_details[j].thread_name_str = NULL;
|
rtos->thread_details[j].thread_name_str = NULL;
|
||||||
}
|
}
|
||||||
if ( rtos->thread_details[j].extra_info_str != NULL )
|
if (rtos->thread_details[j].extra_info_str != NULL) {
|
||||||
{
|
free(rtos->thread_details[j].extra_info_str);
|
||||||
free( rtos->thread_details[j].extra_info_str );
|
|
||||||
rtos->thread_details[j].extra_info_str = NULL;
|
rtos->thread_details[j].extra_info_str = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free( rtos->thread_details );
|
free(rtos->thread_details);
|
||||||
rtos->thread_details = NULL;
|
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);
|
||||||
|
|
||||||
// read the current thread id
|
if (retval != ERROR_OK) {
|
||||||
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");
|
LOG_OUTPUT("Could not read ThreadX current thread from target\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ( thread_list_size == 0 ) || ( rtos->current_thread == 0 ) )
|
if ((thread_list_size == 0) || (rtos->current_thread == 0)) {
|
||||||
{
|
/* Either : No RTOS threads - there is always at least the current execution though */
|
||||||
// Either : No RTOS threads - there is always at least the current execution though
|
/* OR : No current thread - all threads suspended - show the current execution
|
||||||
// OR : No current thread - all threads suspended - show the current execution of idling
|
* of idling */
|
||||||
char tmp_str[] = "Current Execution";
|
char tmp_str[] = "Current Execution";
|
||||||
thread_list_size++;
|
thread_list_size++;
|
||||||
tasks_found++;
|
tasks_found++;
|
||||||
rtos->thread_details = (struct thread_detail*) malloc( sizeof( struct thread_detail ) * thread_list_size );
|
rtos->thread_details = (struct thread_detail *) malloc(
|
||||||
|
sizeof(struct thread_detail) * thread_list_size);
|
||||||
rtos->thread_details->threadid = 1;
|
rtos->thread_details->threadid = 1;
|
||||||
rtos->thread_details->exists = true;
|
rtos->thread_details->exists = true;
|
||||||
rtos->thread_details->display_str = NULL;
|
rtos->thread_details->display_str = NULL;
|
||||||
rtos->thread_details->extra_info_str = NULL;
|
rtos->thread_details->extra_info_str = NULL;
|
||||||
rtos->thread_details->thread_name_str = (char*) malloc( sizeof(tmp_str) );
|
rtos->thread_details->thread_name_str = (char *) malloc(sizeof(tmp_str));
|
||||||
strcpy( rtos->thread_details->thread_name_str, tmp_str );
|
strcpy(rtos->thread_details->thread_name_str, tmp_str);
|
||||||
|
|
||||||
|
if (thread_list_size == 0) {
|
||||||
if ( thread_list_size == 0 )
|
|
||||||
{
|
|
||||||
rtos->thread_count = 1;
|
rtos->thread_count = 1;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
/* create space for new thread details */
|
||||||
{
|
rtos->thread_details = (struct thread_detail *) malloc(
|
||||||
// create space for new thread details
|
sizeof(struct thread_detail) * thread_list_size);
|
||||||
rtos->thread_details = (struct thread_detail*) malloc( sizeof( struct thread_detail ) * thread_list_size );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Read the pointer to the first thread */
|
||||||
|
|
||||||
// Read the pointer to the first thread
|
|
||||||
int64_t thread_ptr = 0;
|
int64_t 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);
|
retval = target_read_buffer(rtos->target,
|
||||||
if ( retval != ERROR_OK )
|
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");
|
LOG_OUTPUT("Could not read ThreadX thread location from target\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* loop over all threads */
|
||||||
// loop over all threads
|
|
||||||
int64_t prev_thread_ptr = 0;
|
int64_t prev_thread_ptr = 0;
|
||||||
while ( ( thread_ptr != prev_thread_ptr ) && ( tasks_found < thread_list_size ) )
|
while ((thread_ptr != prev_thread_ptr) && (tasks_found < thread_list_size)) {
|
||||||
{
|
|
||||||
|
|
||||||
#define THREADX_THREAD_NAME_STR_SIZE (200)
|
#define THREADX_THREAD_NAME_STR_SIZE (200)
|
||||||
char tmp_str[THREADX_THREAD_NAME_STR_SIZE];
|
char tmp_str[THREADX_THREAD_NAME_STR_SIZE];
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
int64_t name_ptr = 0;
|
int64_t name_ptr = 0;
|
||||||
|
|
||||||
// Save the thread pointer
|
/* Save the thread pointer */
|
||||||
rtos->thread_details[tasks_found].threadid = thread_ptr;
|
rtos->thread_details[tasks_found].threadid = thread_ptr;
|
||||||
|
|
||||||
|
/* read the name pointer */
|
||||||
// read the name pointer
|
retval = target_read_buffer(rtos->target,
|
||||||
retval = target_read_buffer( rtos->target, thread_ptr + param->thread_name_offset, param->pointer_width, (uint8_t *)&name_ptr);
|
thread_ptr + param->thread_name_offset,
|
||||||
if ( retval != ERROR_OK )
|
param->pointer_width,
|
||||||
{
|
(uint8_t *)&name_ptr);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
LOG_OUTPUT("Could not read ThreadX thread name pointer from target\r\n");
|
LOG_OUTPUT("Could not read ThreadX thread name pointer from target\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the thread name
|
/* Read the thread name */
|
||||||
retval = target_read_buffer( rtos->target, name_ptr, THREADX_THREAD_NAME_STR_SIZE, (uint8_t *)&tmp_str);
|
retval =
|
||||||
if ( retval != ERROR_OK )
|
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");
|
LOG_OUTPUT("Error reading thread name from ThreadX target\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
tmp_str[THREADX_THREAD_NAME_STR_SIZE-1] = '\x00';
|
tmp_str[THREADX_THREAD_NAME_STR_SIZE-1] = '\x00';
|
||||||
|
|
||||||
if ( tmp_str[0] == '\x00' )
|
if (tmp_str[0] == '\x00')
|
||||||
{
|
strcpy(tmp_str, "No Name");
|
||||||
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].thread_name_str = (char*)malloc( strlen(tmp_str)+1 );
|
/* Read the thread status */
|
||||||
strcpy( rtos->thread_details[tasks_found].thread_name_str, tmp_str );
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Read the thread status
|
|
||||||
int64_t thread_status = 0;
|
int64_t thread_status = 0;
|
||||||
retval = target_read_buffer( rtos->target, thread_ptr + param->thread_state_offset, 4, (uint8_t *)&thread_status);
|
retval = target_read_buffer(rtos->target,
|
||||||
if ( retval != ERROR_OK )
|
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");
|
LOG_OUTPUT("Error reading thread state from ThreadX target\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
for( i = 0; (i < THREADX_NUM_STATES) && (ThreadX_thread_states[i].value!=thread_status); i++ )
|
for (i = 0; (i < THREADX_NUM_STATES) &&
|
||||||
{
|
(ThreadX_thread_states[i].value != thread_status); i++) {
|
||||||
|
/* empty */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *state_desc;
|
||||||
char * state_desc;
|
|
||||||
if (i < THREADX_NUM_STATES)
|
if (i < THREADX_NUM_STATES)
|
||||||
{
|
|
||||||
state_desc = ThreadX_thread_states[i].desc;
|
state_desc = ThreadX_thread_states[i].desc;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
state_desc = "Unknown state";
|
state_desc = "Unknown state";
|
||||||
}
|
|
||||||
|
|
||||||
rtos->thread_details[tasks_found].extra_info_str = (char*)malloc( strlen(state_desc)+1 );
|
rtos->thread_details[tasks_found].extra_info_str = (char *)malloc(strlen(
|
||||||
strcpy( rtos->thread_details[tasks_found].extra_info_str, state_desc );
|
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].exists = true;
|
||||||
|
|
||||||
rtos->thread_details[tasks_found].display_str = NULL;
|
rtos->thread_details[tasks_found].display_str = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
tasks_found++;
|
tasks_found++;
|
||||||
prev_thread_ptr = thread_ptr;
|
prev_thread_ptr = thread_ptr;
|
||||||
|
|
||||||
// Get the location of the next thread structure.
|
/* Get the location of the next thread structure. */
|
||||||
thread_ptr = 0;
|
thread_ptr = 0;
|
||||||
retval = target_read_buffer( rtos->target, prev_thread_ptr + param->thread_next_offset, param->pointer_width, (uint8_t *) &thread_ptr );
|
retval = target_read_buffer(rtos->target,
|
||||||
if ( retval != ERROR_OK )
|
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");
|
LOG_OUTPUT("Error reading next thread pointer in ThreadX thread list\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rtos->thread_count = tasks_found;
|
rtos->thread_count = tasks_found;
|
||||||
|
@ -343,71 +306,60 @@ static int ThreadX_update_threads( struct rtos* rtos)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ThreadX_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char ** hex_reg_list )
|
static int ThreadX_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
|
||||||
{
|
{
|
||||||
|
|
||||||
int retval;
|
int retval;
|
||||||
const struct ThreadX_params* param;
|
const struct ThreadX_params *param;
|
||||||
|
|
||||||
*hex_reg_list = NULL;
|
*hex_reg_list = NULL;
|
||||||
|
|
||||||
if ( rtos == NULL )
|
if (rtos == NULL)
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
if ( thread_id == 0 )
|
if (thread_id == 0)
|
||||||
{
|
|
||||||
return -2;
|
return -2;
|
||||||
}
|
|
||||||
|
|
||||||
if (rtos->rtos_specific_params == NULL )
|
if (rtos->rtos_specific_params == NULL)
|
||||||
{
|
|
||||||
return -3;
|
return -3;
|
||||||
}
|
|
||||||
|
|
||||||
param = (const struct ThreadX_params*) rtos->rtos_specific_params;
|
param = (const struct ThreadX_params *) rtos->rtos_specific_params;
|
||||||
|
|
||||||
// Read the stack pointer
|
/* Read the stack pointer */
|
||||||
int64_t stack_ptr = 0;
|
int64_t stack_ptr = 0;
|
||||||
retval = target_read_buffer( rtos->target, thread_id + param->thread_stack_offset, param->pointer_width, (uint8_t*)&stack_ptr);
|
retval = target_read_buffer(rtos->target,
|
||||||
if ( retval != ERROR_OK )
|
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");
|
LOG_OUTPUT("Error reading stack frame from ThreadX thread\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rtos_generic_stack_read( rtos->target, param->stacking_info, stack_ptr, hex_reg_list );
|
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[])
|
||||||
|
|
||||||
static int ThreadX_get_symbol_list_to_lookup(symbol_table_elem_t * symbol_list[])
|
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
*symbol_list = (symbol_table_elem_t *) malloc( sizeof( symbol_table_elem_t ) * THREADX_NUM_SYMBOLS );
|
*symbol_list = (symbol_table_elem_t *) malloc(
|
||||||
|
sizeof(symbol_table_elem_t) * THREADX_NUM_SYMBOLS);
|
||||||
|
|
||||||
for( i = 0; i < THREADX_NUM_SYMBOLS; i++ )
|
for (i = 0; i < THREADX_NUM_SYMBOLS; i++)
|
||||||
{
|
|
||||||
(*symbol_list)[i].symbol_name = ThreadX_symbol_list[i];
|
(*symbol_list)[i].symbol_name = ThreadX_symbol_list[i];
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ThreadX_detect_rtos( struct target* target )
|
static int ThreadX_detect_rtos(struct target *target)
|
||||||
{
|
{
|
||||||
if ( ( target->rtos->symbols != NULL ) &&
|
if ((target->rtos->symbols != NULL) &&
|
||||||
( target->rtos->symbols[ThreadX_VAL_tx_thread_created_ptr].address != 0 ) )
|
(target->rtos->symbols[ThreadX_VAL_tx_thread_created_ptr].address != 0)) {
|
||||||
{
|
/* looks like ThreadX */
|
||||||
// looks like ThreadX
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
||||||
static int ThreadX_set_current_thread(struct rtos *rtos, threadid_t thread_id)
|
static int ThreadX_set_current_thread(struct rtos *rtos, threadid_t thread_id)
|
||||||
|
@ -415,9 +367,9 @@ static int ThreadX_set_current_thread(struct rtos *rtos, threadid_t thread_id)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ThreadX_get_thread_detail(struct rtos *rtos,
|
||||||
|
threadid_t thread_id,
|
||||||
static int ThreadX_get_thread_detail( struct rtos* rtos, threadid_t thread_id, struct thread_detail* detail )
|
struct thread_detail *detail)
|
||||||
{
|
{
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
int retval;
|
int retval;
|
||||||
|
@ -425,27 +377,20 @@ static int ThreadX_get_thread_detail( struct rtos* rtos, threadid_t thread_i
|
||||||
#define THREADX_THREAD_NAME_STR_SIZE (200)
|
#define THREADX_THREAD_NAME_STR_SIZE (200)
|
||||||
char tmp_str[THREADX_THREAD_NAME_STR_SIZE];
|
char tmp_str[THREADX_THREAD_NAME_STR_SIZE];
|
||||||
|
|
||||||
const struct ThreadX_params* param;
|
const struct ThreadX_params *param;
|
||||||
|
|
||||||
if ( rtos == NULL )
|
if (rtos == NULL)
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
if ( thread_id == 0 )
|
if (thread_id == 0)
|
||||||
{
|
|
||||||
return -2;
|
return -2;
|
||||||
}
|
|
||||||
|
|
||||||
if (rtos->rtos_specific_params == NULL )
|
if (rtos->rtos_specific_params == NULL)
|
||||||
{
|
|
||||||
return -3;
|
return -3;
|
||||||
}
|
|
||||||
|
|
||||||
param = (const struct ThreadX_params*) rtos->rtos_specific_params;
|
param = (const struct ThreadX_params *) rtos->rtos_specific_params;
|
||||||
|
|
||||||
if ( rtos->symbols == NULL )
|
if (rtos->symbols == NULL) {
|
||||||
{
|
|
||||||
LOG_OUTPUT("No symbols for ThreadX\r\n");
|
LOG_OUTPUT("No symbols for ThreadX\r\n");
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
|
@ -453,83 +398,79 @@ static int ThreadX_get_thread_detail( struct rtos* rtos, threadid_t thread_i
|
||||||
detail->threadid = thread_id;
|
detail->threadid = thread_id;
|
||||||
|
|
||||||
int64_t name_ptr = 0;
|
int64_t name_ptr = 0;
|
||||||
// read the name pointer
|
/* read the name pointer */
|
||||||
retval = target_read_buffer( rtos->target, thread_id + param->thread_name_offset, param->pointer_width, (uint8_t *)&name_ptr);
|
retval = target_read_buffer(rtos->target,
|
||||||
if ( retval != ERROR_OK )
|
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");
|
LOG_OUTPUT("Could not read ThreadX thread name pointer from target\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the thread name
|
/* Read the thread name */
|
||||||
retval = target_read_buffer( rtos->target, name_ptr, THREADX_THREAD_NAME_STR_SIZE, (uint8_t *)&tmp_str);
|
retval = target_read_buffer(rtos->target,
|
||||||
if ( retval != ERROR_OK )
|
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");
|
LOG_OUTPUT("Error reading thread name from ThreadX target\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
tmp_str[THREADX_THREAD_NAME_STR_SIZE-1] = '\x00';
|
tmp_str[THREADX_THREAD_NAME_STR_SIZE-1] = '\x00';
|
||||||
|
|
||||||
if ( tmp_str[0] == '\x00' )
|
if (tmp_str[0] == '\x00')
|
||||||
{
|
strcpy(tmp_str, "No Name");
|
||||||
strcpy(tmp_str,"No Name");
|
|
||||||
}
|
|
||||||
|
|
||||||
detail->thread_name_str = (char*)malloc( strlen(tmp_str)+1 );
|
detail->thread_name_str = (char *)malloc(strlen(tmp_str)+1);
|
||||||
|
|
||||||
|
/* Read the thread status */
|
||||||
// Read the thread status
|
|
||||||
int64_t thread_status = 0;
|
int64_t thread_status = 0;
|
||||||
retval = target_read_buffer( rtos->target, thread_id + param->thread_state_offset, 4, (uint8_t *)&thread_status);
|
retval =
|
||||||
if ( retval != ERROR_OK )
|
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");
|
LOG_OUTPUT("Error reading thread state from ThreadX target\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
for( i = 0; (i < THREADX_NUM_STATES) && (ThreadX_thread_states[i].value!=thread_status); i++ )
|
for (i = 0; (i < THREADX_NUM_STATES) &&
|
||||||
{
|
(ThreadX_thread_states[i].value != thread_status); i++) {
|
||||||
|
/* empty */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *state_desc;
|
||||||
char * state_desc;
|
|
||||||
if (i < THREADX_NUM_STATES)
|
if (i < THREADX_NUM_STATES)
|
||||||
{
|
|
||||||
state_desc = ThreadX_thread_states[i].desc;
|
state_desc = ThreadX_thread_states[i].desc;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
state_desc = "Unknown state";
|
state_desc = "Unknown state";
|
||||||
}
|
|
||||||
|
|
||||||
detail->extra_info_str = (char*)malloc( strlen(state_desc)+1 );
|
detail->extra_info_str = (char *)malloc(strlen(state_desc)+1);
|
||||||
|
|
||||||
detail->exists = true;
|
detail->exists = true;
|
||||||
|
|
||||||
detail->display_str = NULL;
|
detail->display_str = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int ThreadX_create( struct target* target )
|
static int ThreadX_create(struct target *target)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while ( ( i < THREADX_NUM_PARAMS ) && ( 0 != strcmp( ThreadX_params_list[i].target_name, target->type->name ) ) )
|
while ((i < THREADX_NUM_PARAMS) &&
|
||||||
{
|
(0 != strcmp(ThreadX_params_list[i].target_name, target->type->name))) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if ( i >= THREADX_NUM_PARAMS )
|
if (i >= THREADX_NUM_PARAMS) {
|
||||||
{
|
|
||||||
LOG_OUTPUT("Could not find target in ThreadX compatibility list\r\n");
|
LOG_OUTPUT("Could not find target in ThreadX compatibility list\r\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
target->rtos->rtos_specific_params = (void*) &ThreadX_params_list[i];
|
target->rtos->rtos_specific_params = (void *) &ThreadX_params_list[i];
|
||||||
target->rtos->current_thread = 0;
|
target->rtos->current_thread = 0;
|
||||||
target->rtos->thread_details = NULL;
|
target->rtos->thread_details = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
399
src/rtos/eCos.c
399
src/rtos/eCos.c
|
@ -28,206 +28,189 @@
|
||||||
#include "helper/log.h"
|
#include "helper/log.h"
|
||||||
#include "rtos_ecos_stackings.h"
|
#include "rtos_ecos_stackings.h"
|
||||||
|
|
||||||
static int eCos_detect_rtos( struct target* target );
|
static int eCos_detect_rtos(struct target *target);
|
||||||
static int eCos_create( struct target* target );
|
static int eCos_create(struct target *target);
|
||||||
static int eCos_update_threads( struct rtos* rtos);
|
static int eCos_update_threads(struct rtos *rtos);
|
||||||
static int eCos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char ** hex_reg_list );
|
static int eCos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list);
|
||||||
static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t * symbol_list[]);
|
static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]);
|
||||||
|
|
||||||
struct eCos_thread_state
|
struct eCos_thread_state {
|
||||||
{
|
|
||||||
int value;
|
int value;
|
||||||
char * desc;
|
char *desc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct eCos_thread_state eCos_thread_states[] = {
|
||||||
struct eCos_thread_state eCos_thread_states[] =
|
{ 0, "Ready" },
|
||||||
{
|
{ 1, "Sleeping" },
|
||||||
{ 0, "Ready" },
|
{ 2, "Countsleep" },
|
||||||
{ 1, "Sleeping" },
|
{ 4, "Suspended" },
|
||||||
{ 2, "Countsleep" },
|
{ 8, "Creating" },
|
||||||
{ 4, "Suspended" },
|
{ 16, "Exited" }
|
||||||
{ 8, "Creating" },
|
|
||||||
{ 16, "Exited" }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ECOS_NUM_STATES (sizeof(eCos_thread_states)/sizeof(struct eCos_thread_state))
|
#define ECOS_NUM_STATES (sizeof(eCos_thread_states)/sizeof(struct eCos_thread_state))
|
||||||
|
|
||||||
struct eCos_params
|
struct eCos_params {
|
||||||
{
|
char *target_name;
|
||||||
char * target_name;
|
unsigned char pointer_width;
|
||||||
unsigned char pointer_width;
|
unsigned char thread_stack_offset;
|
||||||
unsigned char thread_stack_offset;
|
unsigned char thread_name_offset;
|
||||||
unsigned char thread_name_offset;
|
unsigned char thread_state_offset;
|
||||||
unsigned char thread_state_offset;
|
unsigned char thread_next_offset;
|
||||||
unsigned char thread_next_offset;
|
unsigned char thread_uniqueid_offset;
|
||||||
unsigned char thread_uniqueid_offset;
|
const struct rtos_register_stacking *stacking_info;
|
||||||
const struct rtos_register_stacking* stacking_info;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct eCos_params eCos_params_list[] =
|
const struct eCos_params eCos_params_list[] = {
|
||||||
{
|
{
|
||||||
{ "cortex_m3", // target_name
|
"cortex_m3", /* target_name */
|
||||||
4, // pointer_width;
|
4, /* pointer_width; */
|
||||||
0x0c, // thread_stack_offset;
|
0x0c, /* thread_stack_offset; */
|
||||||
0x9c, // thread_name_offset;
|
0x9c, /* thread_name_offset; */
|
||||||
0x3c, // thread_state_offset;
|
0x3c, /* thread_state_offset; */
|
||||||
0xa0, // thread_next_offset
|
0xa0, /* thread_next_offset */
|
||||||
0x4c, // thread_uniqueid_offset
|
0x4c, /* thread_uniqueid_offset */
|
||||||
&rtos_eCos_Cortex_M3_stacking // stacking_info
|
&rtos_eCos_Cortex_M3_stacking /* stacking_info */
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ECOS_NUM_PARAMS ((int)(sizeof(eCos_params_list)/sizeof(struct eCos_params)))
|
#define ECOS_NUM_PARAMS ((int)(sizeof(eCos_params_list)/sizeof(struct eCos_params)))
|
||||||
|
|
||||||
enum eCos_symbol_values
|
enum eCos_symbol_values {
|
||||||
{
|
eCos_VAL_thread_list = 0,
|
||||||
eCos_VAL_thread_list = 0,
|
eCos_VAL_current_thread_ptr = 1
|
||||||
eCos_VAL_current_thread_ptr = 1
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static char* eCos_symbol_list[] =
|
static char *eCos_symbol_list[] = {
|
||||||
{
|
"Cyg_Thread::thread_list",
|
||||||
"Cyg_Thread::thread_list",
|
"Cyg_Scheduler_Base::current_thread",
|
||||||
"Cyg_Scheduler_Base::current_thread",
|
NULL
|
||||||
NULL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define ECOS_NUM_SYMBOLS (sizeof(eCos_symbol_list)/sizeof(char *))
|
||||||
|
|
||||||
|
const struct rtos_type eCos_rtos = {
|
||||||
|
.name = "eCos",
|
||||||
|
|
||||||
#define ECOS_NUM_SYMBOLS (sizeof(eCos_symbol_list)/sizeof(char*))
|
.detect_rtos = eCos_detect_rtos,
|
||||||
|
.create = eCos_create,
|
||||||
|
.update_threads = eCos_update_threads,
|
||||||
const struct rtos_type eCos_rtos =
|
.get_thread_reg_list = eCos_get_thread_reg_list,
|
||||||
{
|
|
||||||
.name = "eCos",
|
|
||||||
|
|
||||||
.detect_rtos = eCos_detect_rtos,
|
|
||||||
.create = eCos_create,
|
|
||||||
.update_threads = eCos_update_threads,
|
|
||||||
.get_thread_reg_list = eCos_get_thread_reg_list,
|
|
||||||
.get_symbol_list_to_lookup = eCos_get_symbol_list_to_lookup,
|
.get_symbol_list_to_lookup = eCos_get_symbol_list_to_lookup,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int eCos_update_threads( struct rtos* rtos)
|
static int eCos_update_threads(struct rtos *rtos)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
int tasks_found = 0;
|
int tasks_found = 0;
|
||||||
int thread_list_size = 0;
|
int thread_list_size = 0;
|
||||||
const struct eCos_params* param;
|
const struct eCos_params *param;
|
||||||
|
|
||||||
if ( rtos == NULL )
|
if (rtos == NULL)
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
if (rtos->rtos_specific_params == NULL )
|
if (rtos->rtos_specific_params == NULL)
|
||||||
{
|
|
||||||
return -3;
|
return -3;
|
||||||
}
|
|
||||||
|
|
||||||
param = (const struct eCos_params*) rtos->rtos_specific_params;
|
param = (const struct eCos_params *) rtos->rtos_specific_params;
|
||||||
|
|
||||||
if ( rtos->symbols == NULL )
|
if (rtos->symbols == NULL) {
|
||||||
{
|
|
||||||
LOG_OUTPUT("No symbols for eCos\r\n");
|
LOG_OUTPUT("No symbols for eCos\r\n");
|
||||||
return -4;
|
return -4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( rtos->symbols[eCos_VAL_thread_list].address == 0 )
|
if (rtos->symbols[eCos_VAL_thread_list].address == 0) {
|
||||||
{
|
|
||||||
LOG_OUTPUT("Don't have the thread list head\r\n");
|
LOG_OUTPUT("Don't have the thread list head\r\n");
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* wipe out previous thread details if any */
|
||||||
// wipe out previous thread details if any
|
if (rtos->thread_details != NULL) {
|
||||||
if ( rtos->thread_details != NULL )
|
|
||||||
{
|
|
||||||
int j;
|
int j;
|
||||||
for( j = 0; j < rtos->thread_count; j++ )
|
for (j = 0; j < rtos->thread_count; j++) {
|
||||||
{
|
if (rtos->thread_details[j].display_str != NULL) {
|
||||||
if ( rtos->thread_details[j].display_str != NULL )
|
free(rtos->thread_details[j].display_str);
|
||||||
{
|
|
||||||
free( rtos->thread_details[j].display_str );
|
|
||||||
rtos->thread_details[j].display_str = NULL;
|
rtos->thread_details[j].display_str = NULL;
|
||||||
}
|
}
|
||||||
if ( rtos->thread_details[j].thread_name_str != NULL )
|
if (rtos->thread_details[j].thread_name_str != NULL) {
|
||||||
{
|
free(rtos->thread_details[j].thread_name_str);
|
||||||
free( rtos->thread_details[j].thread_name_str );
|
|
||||||
rtos->thread_details[j].thread_name_str = NULL;
|
rtos->thread_details[j].thread_name_str = NULL;
|
||||||
}
|
}
|
||||||
if ( rtos->thread_details[j].extra_info_str != NULL )
|
if (rtos->thread_details[j].extra_info_str != NULL) {
|
||||||
{
|
free(rtos->thread_details[j].extra_info_str);
|
||||||
free( rtos->thread_details[j].extra_info_str );
|
|
||||||
rtos->thread_details[j].extra_info_str = NULL;
|
rtos->thread_details[j].extra_info_str = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free( rtos->thread_details );
|
free(rtos->thread_details);
|
||||||
rtos->thread_details = NULL;
|
rtos->thread_details = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* determine the number of current threads */
|
||||||
// determine the number of current threads
|
|
||||||
uint32_t thread_list_head = rtos->symbols[eCos_VAL_thread_list].address;
|
uint32_t thread_list_head = rtos->symbols[eCos_VAL_thread_list].address;
|
||||||
uint32_t thread_index;
|
uint32_t thread_index;
|
||||||
target_read_buffer( rtos->target, thread_list_head, param->pointer_width, (uint8_t *) &thread_index );
|
target_read_buffer(rtos->target,
|
||||||
|
thread_list_head,
|
||||||
|
param->pointer_width,
|
||||||
|
(uint8_t *) &thread_index);
|
||||||
uint32_t first_thread = thread_index;
|
uint32_t first_thread = thread_index;
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
thread_list_size++;
|
thread_list_size++;
|
||||||
retval = target_read_buffer( rtos->target, thread_index + param->thread_next_offset, param->pointer_width, (uint8_t *) &thread_index );
|
retval = target_read_buffer(rtos->target,
|
||||||
|
thread_index + param->thread_next_offset,
|
||||||
|
param->pointer_width,
|
||||||
|
(uint8_t *) &thread_index);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
} while( thread_index!=first_thread );
|
} while (thread_index != first_thread);
|
||||||
|
|
||||||
// read the current thread id
|
/* read the current thread id */
|
||||||
uint32_t current_thread_addr;
|
uint32_t current_thread_addr;
|
||||||
retval = target_read_buffer( rtos->target, rtos->symbols[eCos_VAL_current_thread_ptr].address, 4, (uint8_t *)¤t_thread_addr);
|
retval = target_read_buffer(rtos->target,
|
||||||
|
rtos->symbols[eCos_VAL_current_thread_ptr].address,
|
||||||
|
4,
|
||||||
|
(uint8_t *)¤t_thread_addr);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
rtos->current_thread = 0;
|
rtos->current_thread = 0;
|
||||||
retval = target_read_buffer( rtos->target, current_thread_addr + param->thread_uniqueid_offset, 2, (uint8_t *)&rtos->current_thread);
|
retval = target_read_buffer(rtos->target,
|
||||||
if ( retval != ERROR_OK )
|
current_thread_addr + param->thread_uniqueid_offset,
|
||||||
{
|
2,
|
||||||
|
(uint8_t *)&rtos->current_thread);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
LOG_OUTPUT("Could not read eCos current thread from target\r\n");
|
LOG_OUTPUT("Could not read eCos current thread from target\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ( thread_list_size == 0 ) || ( rtos->current_thread == 0 ) )
|
if ((thread_list_size == 0) || (rtos->current_thread == 0)) {
|
||||||
{
|
/* Either : No RTOS threads - there is always at least the current execution though */
|
||||||
// Either : No RTOS threads - there is always at least the current execution though
|
/* OR : No current thread - all threads suspended - show the current execution
|
||||||
// OR : No current thread - all threads suspended - show the current execution of idling
|
* of idling */
|
||||||
char tmp_str[] = "Current Execution";
|
char tmp_str[] = "Current Execution";
|
||||||
thread_list_size++;
|
thread_list_size++;
|
||||||
tasks_found++;
|
tasks_found++;
|
||||||
rtos->thread_details = (struct thread_detail*) malloc( sizeof( struct thread_detail ) * thread_list_size );
|
rtos->thread_details = (struct thread_detail *) malloc(
|
||||||
|
sizeof(struct thread_detail) * thread_list_size);
|
||||||
rtos->thread_details->threadid = 1;
|
rtos->thread_details->threadid = 1;
|
||||||
rtos->thread_details->exists = true;
|
rtos->thread_details->exists = true;
|
||||||
rtos->thread_details->display_str = NULL;
|
rtos->thread_details->display_str = NULL;
|
||||||
rtos->thread_details->extra_info_str = NULL;
|
rtos->thread_details->extra_info_str = NULL;
|
||||||
rtos->thread_details->thread_name_str = (char*) malloc( sizeof(tmp_str) );
|
rtos->thread_details->thread_name_str = (char *) malloc(sizeof(tmp_str));
|
||||||
strcpy( rtos->thread_details->thread_name_str, tmp_str );
|
strcpy(rtos->thread_details->thread_name_str, tmp_str);
|
||||||
|
|
||||||
|
if (thread_list_size == 0) {
|
||||||
if ( thread_list_size == 0 )
|
|
||||||
{
|
|
||||||
rtos->thread_count = 1;
|
rtos->thread_count = 1;
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
/* create space for new thread details */
|
||||||
{
|
rtos->thread_details = (struct thread_detail *) malloc(
|
||||||
// create space for new thread details
|
sizeof(struct thread_detail) * thread_list_size);
|
||||||
rtos->thread_details = (struct thread_detail*) malloc( sizeof( struct thread_detail ) * thread_list_size );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop over all threads
|
/* loop over all threads */
|
||||||
thread_index = first_thread;
|
thread_index = first_thread;
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
|
|
||||||
#define ECOS_THREAD_NAME_STR_SIZE (200)
|
#define ECOS_THREAD_NAME_STR_SIZE (200)
|
||||||
char tmp_str[ECOS_THREAD_NAME_STR_SIZE];
|
char tmp_str[ECOS_THREAD_NAME_STR_SIZE];
|
||||||
|
@ -235,196 +218,198 @@ static int eCos_update_threads( struct rtos* rtos)
|
||||||
uint32_t name_ptr = 0;
|
uint32_t name_ptr = 0;
|
||||||
uint32_t prev_thread_ptr;
|
uint32_t prev_thread_ptr;
|
||||||
|
|
||||||
// Save the thread pointer
|
/* Save the thread pointer */
|
||||||
uint16_t thread_id;
|
uint16_t thread_id;
|
||||||
retval = target_read_buffer( rtos->target, thread_index + param->thread_uniqueid_offset, 2, (uint8_t *)&thread_id);
|
retval = target_read_buffer(rtos->target,
|
||||||
if ( retval != ERROR_OK )
|
thread_index + param->thread_uniqueid_offset,
|
||||||
{
|
2,
|
||||||
|
(uint8_t *)&thread_id);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
LOG_OUTPUT("Could not read eCos thread id from target\r\n");
|
LOG_OUTPUT("Could not read eCos thread id from target\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
rtos->thread_details[tasks_found].threadid = thread_id;
|
rtos->thread_details[tasks_found].threadid = thread_id;
|
||||||
|
|
||||||
// read the name pointer
|
/* read the name pointer */
|
||||||
retval = target_read_buffer( rtos->target, thread_index + param->thread_name_offset, param->pointer_width, (uint8_t *)&name_ptr);
|
retval = target_read_buffer(rtos->target,
|
||||||
if ( retval != ERROR_OK )
|
thread_index + param->thread_name_offset,
|
||||||
{
|
param->pointer_width,
|
||||||
|
(uint8_t *)&name_ptr);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
LOG_OUTPUT("Could not read eCos thread name pointer from target\r\n");
|
LOG_OUTPUT("Could not read eCos thread name pointer from target\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the thread name
|
/* Read the thread name */
|
||||||
retval = target_read_buffer( rtos->target, name_ptr, ECOS_THREAD_NAME_STR_SIZE, (uint8_t *)&tmp_str);
|
retval =
|
||||||
if ( retval != ERROR_OK )
|
target_read_buffer(rtos->target,
|
||||||
{
|
name_ptr,
|
||||||
|
ECOS_THREAD_NAME_STR_SIZE,
|
||||||
|
(uint8_t *)&tmp_str);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
LOG_OUTPUT("Error reading thread name from eCos target\r\n");
|
LOG_OUTPUT("Error reading thread name from eCos target\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
tmp_str[ECOS_THREAD_NAME_STR_SIZE-1] = '\x00';
|
tmp_str[ECOS_THREAD_NAME_STR_SIZE-1] = '\x00';
|
||||||
|
|
||||||
if ( tmp_str[0] == '\x00' )
|
if (tmp_str[0] == '\x00')
|
||||||
{
|
strcpy(tmp_str, "No Name");
|
||||||
strcpy(tmp_str,"No Name");
|
|
||||||
}
|
|
||||||
|
|
||||||
rtos->thread_details[tasks_found].thread_name_str = (char*)malloc( strlen(tmp_str)+1 );
|
rtos->thread_details[tasks_found].thread_name_str =
|
||||||
strcpy( rtos->thread_details[tasks_found].thread_name_str, tmp_str );
|
(char *)malloc(strlen(tmp_str)+1);
|
||||||
|
strcpy(rtos->thread_details[tasks_found].thread_name_str, tmp_str);
|
||||||
|
|
||||||
// Read the thread status
|
/* Read the thread status */
|
||||||
int64_t thread_status = 0;
|
int64_t thread_status = 0;
|
||||||
retval = target_read_buffer( rtos->target, thread_index + param->thread_state_offset, 4, (uint8_t *)&thread_status);
|
retval = target_read_buffer(rtos->target,
|
||||||
if ( retval != ERROR_OK )
|
thread_index + param->thread_state_offset,
|
||||||
{
|
4,
|
||||||
|
(uint8_t *)&thread_status);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
LOG_OUTPUT("Error reading thread state from eCos target\r\n");
|
LOG_OUTPUT("Error reading thread state from eCos target\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
for( i = 0; (i < ECOS_NUM_STATES) && (eCos_thread_states[i].value!=thread_status); i++ )
|
for (i = 0; (i < ECOS_NUM_STATES) && (eCos_thread_states[i].value != thread_status); i++) {
|
||||||
{
|
/*
|
||||||
|
* empty
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
char * state_desc;
|
char *state_desc;
|
||||||
if (i < ECOS_NUM_STATES)
|
if (i < ECOS_NUM_STATES)
|
||||||
{
|
|
||||||
state_desc = eCos_thread_states[i].desc;
|
state_desc = eCos_thread_states[i].desc;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
state_desc = "Unknown state";
|
state_desc = "Unknown state";
|
||||||
}
|
|
||||||
|
|
||||||
rtos->thread_details[tasks_found].extra_info_str = (char*)malloc( strlen(state_desc)+1 );
|
rtos->thread_details[tasks_found].extra_info_str = (char *)malloc(strlen(
|
||||||
strcpy( rtos->thread_details[tasks_found].extra_info_str, state_desc );
|
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].exists = true;
|
||||||
|
|
||||||
rtos->thread_details[tasks_found].display_str = NULL;
|
rtos->thread_details[tasks_found].display_str = NULL;
|
||||||
|
|
||||||
|
|
||||||
tasks_found++;
|
tasks_found++;
|
||||||
prev_thread_ptr = thread_index;
|
prev_thread_ptr = thread_index;
|
||||||
|
|
||||||
// Get the location of the next thread structure.
|
/* Get the location of the next thread structure. */
|
||||||
thread_index = rtos->symbols[eCos_VAL_thread_list].address;
|
thread_index = rtos->symbols[eCos_VAL_thread_list].address;
|
||||||
retval = target_read_buffer( rtos->target, prev_thread_ptr + param->thread_next_offset, param->pointer_width, (uint8_t *) &thread_index );
|
retval = target_read_buffer(rtos->target,
|
||||||
if ( retval != ERROR_OK )
|
prev_thread_ptr + param->thread_next_offset,
|
||||||
{
|
param->pointer_width,
|
||||||
|
(uint8_t *) &thread_index);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
LOG_OUTPUT("Error reading next thread pointer in eCos thread list\r\n");
|
LOG_OUTPUT("Error reading next thread pointer in eCos thread list\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
}
|
} while (thread_index != first_thread);
|
||||||
while( thread_index!=first_thread );
|
|
||||||
|
|
||||||
rtos->thread_count = tasks_found;
|
rtos->thread_count = tasks_found;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int eCos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char ** hex_reg_list )
|
static int eCos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
|
||||||
{
|
{
|
||||||
|
|
||||||
int retval;
|
int retval;
|
||||||
const struct eCos_params* param;
|
const struct eCos_params *param;
|
||||||
|
|
||||||
*hex_reg_list = NULL;
|
*hex_reg_list = NULL;
|
||||||
|
|
||||||
if ( rtos == NULL )
|
if (rtos == NULL)
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
if ( thread_id == 0 )
|
if (thread_id == 0)
|
||||||
{
|
|
||||||
return -2;
|
return -2;
|
||||||
}
|
|
||||||
|
|
||||||
if (rtos->rtos_specific_params == NULL )
|
if (rtos->rtos_specific_params == NULL)
|
||||||
{
|
|
||||||
return -3;
|
return -3;
|
||||||
}
|
|
||||||
|
|
||||||
param = (const struct eCos_params*) rtos->rtos_specific_params;
|
param = (const struct eCos_params *) rtos->rtos_specific_params;
|
||||||
|
|
||||||
|
/* Find the thread with that thread id */
|
||||||
// Find the thread with that thread id
|
uint16_t id = 0;
|
||||||
uint16_t id=0;
|
|
||||||
uint32_t thread_list_head = rtos->symbols[eCos_VAL_thread_list].address;
|
uint32_t thread_list_head = rtos->symbols[eCos_VAL_thread_list].address;
|
||||||
uint32_t thread_index;
|
uint32_t thread_index;
|
||||||
target_read_buffer( rtos->target, thread_list_head, param->pointer_width, (uint8_t *) &thread_index );
|
target_read_buffer(rtos->target, thread_list_head, param->pointer_width,
|
||||||
bool done=false;
|
(uint8_t *)&thread_index);
|
||||||
while(!done)
|
bool done = false;
|
||||||
{
|
while (!done) {
|
||||||
retval = target_read_buffer( rtos->target, thread_index + param->thread_uniqueid_offset, 2, (uint8_t*)&id);
|
retval = target_read_buffer(rtos->target,
|
||||||
if ( retval != ERROR_OK )
|
thread_index + param->thread_uniqueid_offset,
|
||||||
{
|
2,
|
||||||
|
(uint8_t *)&id);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
LOG_OUTPUT("Error reading unique id from eCos thread\r\n");
|
LOG_OUTPUT("Error reading unique id from eCos thread\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( id==thread_id )
|
if (id == thread_id) {
|
||||||
{
|
done = true;
|
||||||
done=true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
target_read_buffer( rtos->target, thread_index + param->thread_next_offset, param->pointer_width, (uint8_t *) &thread_index );
|
target_read_buffer(rtos->target,
|
||||||
|
thread_index + param->thread_next_offset,
|
||||||
|
param->pointer_width,
|
||||||
|
(uint8_t *) &thread_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(done)
|
if (done) {
|
||||||
{
|
/* Read the stack pointer */
|
||||||
// Read the stack pointer
|
|
||||||
int64_t stack_ptr = 0;
|
int64_t stack_ptr = 0;
|
||||||
retval = target_read_buffer( rtos->target, thread_index + param->thread_stack_offset, param->pointer_width, (uint8_t*)&stack_ptr);
|
retval = target_read_buffer(rtos->target,
|
||||||
if ( retval != ERROR_OK )
|
thread_index + param->thread_stack_offset,
|
||||||
{
|
param->pointer_width,
|
||||||
|
(uint8_t *)&stack_ptr);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
LOG_OUTPUT("Error reading stack frame from eCos thread\r\n");
|
LOG_OUTPUT("Error reading stack frame from eCos thread\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rtos_generic_stack_read( rtos->target, param->stacking_info, stack_ptr, hex_reg_list );
|
return rtos_generic_stack_read(rtos->target,
|
||||||
|
param->stacking_info,
|
||||||
|
stack_ptr,
|
||||||
|
hex_reg_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
|
||||||
|
|
||||||
static int eCos_get_symbol_list_to_lookup(symbol_table_elem_t * symbol_list[])
|
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
*symbol_list = (symbol_table_elem_t *) malloc( sizeof( symbol_table_elem_t ) * ECOS_NUM_SYMBOLS );
|
*symbol_list = (symbol_table_elem_t *) malloc(
|
||||||
|
sizeof(symbol_table_elem_t) * ECOS_NUM_SYMBOLS);
|
||||||
|
|
||||||
for( i = 0; i < ECOS_NUM_SYMBOLS; i++ )
|
for (i = 0; i < ECOS_NUM_SYMBOLS; i++)
|
||||||
{
|
|
||||||
(*symbol_list)[i].symbol_name = eCos_symbol_list[i];
|
(*symbol_list)[i].symbol_name = eCos_symbol_list[i];
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int eCos_detect_rtos( struct target* target )
|
static int eCos_detect_rtos(struct target *target)
|
||||||
{
|
{
|
||||||
if ( ( target->rtos->symbols != NULL ) &&
|
if ((target->rtos->symbols != NULL) &&
|
||||||
( target->rtos->symbols[eCos_VAL_thread_list].address != 0 ) )
|
(target->rtos->symbols[eCos_VAL_thread_list].address != 0)) {
|
||||||
{
|
/* looks like eCos */
|
||||||
// looks like eCos
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int eCos_create( struct target* target )
|
static int eCos_create(struct target *target)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while ( ( i < ECOS_NUM_PARAMS ) && ( 0 != strcmp( eCos_params_list[i].target_name, target->type->name ) ) )
|
while ((i < ECOS_NUM_PARAMS) &&
|
||||||
{
|
(0 != strcmp(eCos_params_list[i].target_name, target->type->name))) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if ( i >= ECOS_NUM_PARAMS )
|
if (i >= ECOS_NUM_PARAMS) {
|
||||||
{
|
|
||||||
LOG_OUTPUT("Could not find target in eCos compatibility list\r\n");
|
LOG_OUTPUT("Could not find target in eCos compatibility list\r\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
target->rtos->rtos_specific_params = (void*) &eCos_params_list[i];
|
target->rtos->rtos_specific_params = (void *) &eCos_params_list[i];
|
||||||
target->rtos->current_thread = 0;
|
target->rtos->current_thread = 0;
|
||||||
target->rtos->thread_details = NULL;
|
target->rtos->thread_details = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
503
src/rtos/linux.c
503
src/rtos/linux.c
File diff suppressed because it is too large
Load Diff
388
src/rtos/rtos.c
388
src/rtos/rtos.c
|
@ -22,16 +22,12 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "rtos.h"
|
#include "rtos.h"
|
||||||
#include "target/target.h"
|
#include "target/target.h"
|
||||||
#include "helper/log.h"
|
#include "helper/log.h"
|
||||||
#include "server/gdb_server.h"
|
#include "server/gdb_server.h"
|
||||||
|
|
||||||
|
static void hex_to_str(char *dst, char *hex_src);
|
||||||
|
|
||||||
static void hex_to_str( char* dst, char * hex_src );
|
|
||||||
|
|
||||||
|
|
||||||
/* RTOSs */
|
/* RTOSs */
|
||||||
extern struct rtos_type FreeRTOS_rtos;
|
extern struct rtos_type FreeRTOS_rtos;
|
||||||
|
@ -39,8 +35,7 @@ extern struct rtos_type ThreadX_rtos;
|
||||||
extern struct rtos_type eCos_rtos;
|
extern struct rtos_type eCos_rtos;
|
||||||
extern struct rtos_type Linux_os;
|
extern struct rtos_type Linux_os;
|
||||||
|
|
||||||
static struct rtos_type *rtos_types[] =
|
static struct rtos_type *rtos_types[] = {
|
||||||
{
|
|
||||||
&ThreadX_rtos,
|
&ThreadX_rtos,
|
||||||
&FreeRTOS_rtos,
|
&FreeRTOS_rtos,
|
||||||
&eCos_rtos,
|
&eCos_rtos,
|
||||||
|
@ -57,69 +52,66 @@ int rtos_smp_init(struct target *target)
|
||||||
return ERROR_TARGET_INIT_FAILED;
|
return ERROR_TARGET_INIT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rtos_create(Jim_GetOptInfo *goi, struct target *target)
|
||||||
int rtos_create(Jim_GetOptInfo *goi, struct target * target)
|
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
char *cp;
|
char *cp;
|
||||||
if (! goi->isconfigure) {
|
if (!goi->isconfigure) {
|
||||||
if (goi->argc != 0) {
|
if (goi->argc != 0) {
|
||||||
if (goi->argc != 0) {
|
if (goi->argc != 0) {
|
||||||
Jim_WrongNumArgs(goi->interp,
|
Jim_WrongNumArgs(goi->interp,
|
||||||
goi->argc, goi->argv,
|
goi->argc, goi->argv,
|
||||||
"NO PARAMS");
|
"NO PARAMS");
|
||||||
return JIM_ERR;
|
return JIM_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
Jim_SetResultString(goi->interp,
|
Jim_SetResultString(goi->interp,
|
||||||
target_type_name(target), -1);
|
target_type_name(target), -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target->rtos) {
|
if (target->rtos)
|
||||||
free((void *)(target->rtos));
|
free((void *)(target->rtos));
|
||||||
}
|
/* e = Jim_GetOpt_String(goi,
|
||||||
// e = Jim_GetOpt_String(goi, &cp, NULL);
|
* &cp, NULL); */
|
||||||
// target->rtos = strdup(cp);
|
/* target->rtos = strdup(cp); */
|
||||||
|
|
||||||
Jim_GetOpt_String(goi, &cp, NULL);
|
Jim_GetOpt_String(goi, &cp, NULL);
|
||||||
/* now does target type exist */
|
/* now does target type exist */
|
||||||
|
|
||||||
if ( 0 == strcmp( cp, "auto") )
|
if (0 == strcmp(cp, "auto")) {
|
||||||
{
|
/* auto detection of RTOS */
|
||||||
// auto detection of RTOS
|
|
||||||
target->rtos_auto_detect = true;
|
target->rtos_auto_detect = true;
|
||||||
x = 0;
|
x = 0;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
for (x = 0 ; rtos_types[x] ; x++) {
|
for (x = 0; rtos_types[x]; x++) {
|
||||||
if (0 == strcmp(cp, rtos_types[x]->name)) {
|
if (0 == strcmp(cp, rtos_types[x]->name)) {
|
||||||
/* found */
|
/* found */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rtos_types[x] == NULL) {
|
if (rtos_types[x] == NULL) {
|
||||||
Jim_SetResultFormatted(goi->interp, "Unknown rtos type %s, try one of ", cp);
|
Jim_SetResultFormatted(goi->interp, "Unknown rtos type %s, try one of ",
|
||||||
for (x = 0 ; rtos_types[x] ; x++) {
|
cp);
|
||||||
|
for (x = 0; rtos_types[x]; x++) {
|
||||||
if (rtos_types[x + 1]) {
|
if (rtos_types[x + 1]) {
|
||||||
Jim_AppendStrings(goi->interp,
|
Jim_AppendStrings(goi->interp,
|
||||||
Jim_GetResult(goi->interp),
|
Jim_GetResult(goi->interp),
|
||||||
rtos_types[x]->name,
|
rtos_types[x]->name,
|
||||||
", ", NULL);
|
", ", NULL);
|
||||||
} else {
|
} else {
|
||||||
Jim_AppendStrings(goi->interp,
|
Jim_AppendStrings(goi->interp,
|
||||||
Jim_GetResult(goi->interp),
|
Jim_GetResult(goi->interp),
|
||||||
" or ",
|
" or ",
|
||||||
rtos_types[x]->name,NULL);
|
rtos_types[x]->name, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return JIM_ERR;
|
return JIM_ERR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Create it */
|
/* Create it */
|
||||||
target->rtos = calloc(1,sizeof(struct rtos));
|
target->rtos = calloc(1, sizeof(struct rtos));
|
||||||
target->rtos->type = rtos_types[x];
|
target->rtos->type = rtos_types[x];
|
||||||
target->rtos->current_threadid = -1;
|
target->rtos->current_threadid = -1;
|
||||||
target->rtos->current_thread = 0;
|
target->rtos->current_thread = 0;
|
||||||
|
@ -128,10 +120,8 @@ int rtos_create(Jim_GetOptInfo *goi, struct target * target)
|
||||||
/* put default thread handler in linux usecase it is overloaded*/
|
/* put default thread handler in linux usecase it is overloaded*/
|
||||||
target->rtos->gdb_thread_packet = rtos_thread_packet;
|
target->rtos->gdb_thread_packet = rtos_thread_packet;
|
||||||
|
|
||||||
if ( 0 != strcmp( cp, "auto") )
|
if (0 != strcmp(cp, "auto"))
|
||||||
{
|
target->rtos->type->create(target);
|
||||||
target->rtos->type->create( target );
|
|
||||||
}
|
|
||||||
|
|
||||||
return JIM_OK;
|
return JIM_OK;
|
||||||
}
|
}
|
||||||
|
@ -140,7 +130,8 @@ int gdb_thread_packet(struct connection *connection, char *packet, int packet_si
|
||||||
{
|
{
|
||||||
struct target *target = get_target_from_connection(connection);
|
struct target *target = get_target_from_connection(connection);
|
||||||
if (target->rtos == NULL)
|
if (target->rtos == NULL)
|
||||||
return rtos_thread_packet(connection, packet, packet_size); /* thread not found*/
|
return rtos_thread_packet(connection, packet, packet_size); /* thread not
|
||||||
|
*found*/
|
||||||
return target->rtos->gdb_thread_packet(connection, packet, packet_size);
|
return target->rtos->gdb_thread_packet(connection, packet, packet_size);
|
||||||
}
|
}
|
||||||
/* return -1 if no rtos defined, 0 if rtos and symbol to be asked, 1 if all
|
/* return -1 if no rtos defined, 0 if rtos and symbol to be asked, 1 if all
|
||||||
|
@ -171,8 +162,8 @@ int rtos_qsymbol(struct connection *connection, char *packet, int packet_size)
|
||||||
|
|
||||||
hex_to_str(name_str, hex_name_str);
|
hex_to_str(name_str, hex_name_str);
|
||||||
symbol_num = 0;
|
symbol_num = 0;
|
||||||
while ((target->rtos->symbols[symbol_num].symbol_name != NULL)
|
while ((target->rtos->symbols[symbol_num].symbol_name != NULL) &&
|
||||||
&& (0 != strcmp(target->rtos->symbols[symbol_num].symbol_name, name_str)))
|
(0 != strcmp(target->rtos->symbols[symbol_num].symbol_name, name_str)))
|
||||||
symbol_num++;
|
symbol_num++;
|
||||||
|
|
||||||
if (target->rtos->symbols[symbol_num].symbol_name == NULL) {
|
if (target->rtos->symbols[symbol_num].symbol_name == NULL) {
|
||||||
|
@ -194,7 +185,8 @@ int rtos_qsymbol(struct connection *connection, char *packet, int packet_size)
|
||||||
(1 == target->rtos->type->detect_rtos(target))) {
|
(1 == target->rtos->type->detect_rtos(target))) {
|
||||||
/* Found correct RTOS or not autodetecting */
|
/* Found correct RTOS or not autodetecting */
|
||||||
if (target->rtos_auto_detect == true)
|
if (target->rtos_auto_detect == true)
|
||||||
LOG_OUTPUT("Auto-detected RTOS: %s\r\n", target->rtos->type->name);
|
LOG_OUTPUT("Auto-detected RTOS: %s\r\n",
|
||||||
|
target->rtos->type->name);
|
||||||
symbols_done = 1;
|
symbols_done = 1;
|
||||||
} else {
|
} else {
|
||||||
/* Auto detecting RTOS and currently not found */
|
/* Auto detecting RTOS and currently not found */
|
||||||
|
@ -203,7 +195,8 @@ int rtos_qsymbol(struct connection *connection, char *packet, int packet_size)
|
||||||
symbols_done = 1;
|
symbols_done = 1;
|
||||||
else {
|
else {
|
||||||
next_symbol_num = 0;
|
next_symbol_num = 0;
|
||||||
target->rtos->type->get_symbol_list_to_lookup(&target->rtos->symbols);
|
target->rtos->type->get_symbol_list_to_lookup(
|
||||||
|
&target->rtos->symbols);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -225,82 +218,63 @@ int rtos_qsymbol(struct connection *connection, char *packet, int packet_size)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int rtos_thread_packet(struct connection *connection, char *packet, int packet_size)
|
int rtos_thread_packet(struct connection *connection, char *packet, int packet_size)
|
||||||
{
|
{
|
||||||
struct target *target = get_target_from_connection(connection);
|
struct target *target = get_target_from_connection(connection);
|
||||||
|
|
||||||
if (strstr(packet, "qThreadExtraInfo,"))
|
if (strstr(packet, "qThreadExtraInfo,")) {
|
||||||
{
|
if ((target->rtos != NULL) && (target->rtos->thread_details != NULL) &&
|
||||||
if ((target->rtos != NULL) && (target->rtos->thread_details != NULL) && (target->rtos->thread_count != 0))
|
(target->rtos->thread_count != 0)) {
|
||||||
{
|
|
||||||
threadid_t threadid = 0;
|
threadid_t threadid = 0;
|
||||||
int found = -1;
|
int found = -1;
|
||||||
sscanf(packet, "qThreadExtraInfo,%" SCNx64, &threadid );
|
sscanf(packet, "qThreadExtraInfo,%" SCNx64, &threadid);
|
||||||
|
|
||||||
if ((target->rtos != NULL) && (target->rtos->thread_details
|
if ((target->rtos != NULL) && (target->rtos->thread_details != NULL)) {
|
||||||
!= NULL)) {
|
|
||||||
int thread_num;
|
int thread_num;
|
||||||
for (thread_num = 0; thread_num
|
for (thread_num = 0; thread_num < target->rtos->thread_count; thread_num++) {
|
||||||
< target->rtos->thread_count; thread_num++) {
|
if (target->rtos->thread_details[thread_num].threadid == threadid) {
|
||||||
if (target->rtos->thread_details[thread_num].threadid
|
if (target->rtos->thread_details[thread_num].exists)
|
||||||
== threadid) {
|
|
||||||
if (target->rtos->thread_details[thread_num].exists) {
|
|
||||||
found = thread_num;
|
found = thread_num;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (found == -1) {
|
if (found == -1) {
|
||||||
gdb_put_packet(connection, "E01", 3); // thread not found
|
gdb_put_packet(connection, "E01", 3); /* thread not found */
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct thread_detail* detail = &target->rtos->thread_details[found];
|
struct thread_detail *detail = &target->rtos->thread_details[found];
|
||||||
|
|
||||||
int str_size = 0;
|
int str_size = 0;
|
||||||
if ( detail->display_str != NULL )
|
if (detail->display_str != NULL)
|
||||||
{
|
|
||||||
str_size += strlen(detail->display_str);
|
str_size += strlen(detail->display_str);
|
||||||
}
|
if (detail->thread_name_str != NULL)
|
||||||
if ( detail->thread_name_str != NULL )
|
|
||||||
{
|
|
||||||
str_size += strlen(detail->thread_name_str);
|
str_size += strlen(detail->thread_name_str);
|
||||||
}
|
if (detail->extra_info_str != NULL)
|
||||||
if ( detail->extra_info_str != NULL )
|
|
||||||
{
|
|
||||||
str_size += strlen(detail->extra_info_str);
|
str_size += strlen(detail->extra_info_str);
|
||||||
}
|
|
||||||
|
|
||||||
char * tmp_str = (char*) malloc( str_size + 7 );
|
char *tmp_str = (char *) malloc(str_size + 7);
|
||||||
char* tmp_str_ptr = tmp_str;
|
char *tmp_str_ptr = tmp_str;
|
||||||
|
|
||||||
if ( detail->display_str != NULL )
|
if (detail->display_str != NULL)
|
||||||
{
|
tmp_str_ptr += sprintf(tmp_str_ptr, "%s", detail->display_str);
|
||||||
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->thread_name_str != NULL )
|
if (detail->extra_info_str != NULL) {
|
||||||
{
|
if (tmp_str_ptr != tmp_str)
|
||||||
if ( tmp_str_ptr != tmp_str )
|
tmp_str_ptr += sprintf(tmp_str_ptr, " : ");
|
||||||
{
|
tmp_str_ptr +=
|
||||||
tmp_str_ptr += sprintf( tmp_str_ptr, " : " );
|
sprintf(tmp_str_ptr, " : %s", detail->extra_info_str);
|
||||||
}
|
|
||||||
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 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(strlen(tmp_str) ==
|
assert(strlen(tmp_str) ==
|
||||||
(size_t) (tmp_str_ptr - tmp_str));
|
(size_t) (tmp_str_ptr - tmp_str));
|
||||||
|
|
||||||
char * hex_str = (char*) malloc( strlen(tmp_str)*2 +1 );
|
char *hex_str = (char *) malloc(strlen(tmp_str)*2 + 1);
|
||||||
str_to_hex( hex_str, tmp_str );
|
str_to_hex(hex_str, tmp_str);
|
||||||
|
|
||||||
gdb_put_packet(connection, hex_str, strlen(hex_str));
|
gdb_put_packet(connection, hex_str, strlen(hex_str));
|
||||||
free(hex_str);
|
free(hex_str);
|
||||||
|
@ -310,11 +284,8 @@ int rtos_thread_packet(struct connection *connection, char *packet, int packet_s
|
||||||
}
|
}
|
||||||
gdb_put_packet(connection, "", 0);
|
gdb_put_packet(connection, "", 0);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
} else if (strstr(packet, "qSymbol")) {
|
||||||
else if (strstr(packet, "qSymbol"))
|
if (rtos_qsymbol(connection, packet, packet_size) == 1) {
|
||||||
{
|
|
||||||
if (rtos_qsymbol(connection, packet, packet_size) == 1)
|
|
||||||
{
|
|
||||||
target->rtos_auto_detect = false;
|
target->rtos_auto_detect = false;
|
||||||
target->rtos->type->create(target);
|
target->rtos->type->create(target);
|
||||||
target->rtos->type->update_threads(target->rtos);
|
target->rtos->type->update_threads(target->rtos);
|
||||||
|
@ -322,91 +293,64 @@ int rtos_thread_packet(struct connection *connection, char *packet, int packet_s
|
||||||
gdb_put_packet(connection, "OK", 2);
|
gdb_put_packet(connection, "OK", 2);
|
||||||
}
|
}
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
} else if (strstr(packet, "qfThreadInfo")) {
|
||||||
else if (strstr(packet, "qfThreadInfo"))
|
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
if ( ( target->rtos != NULL ) && ( target->rtos->thread_count != 0 ) )
|
if ((target->rtos != NULL) && (target->rtos->thread_count != 0)) {
|
||||||
{
|
|
||||||
|
|
||||||
char* out_str = (char*) malloc(17 * target->rtos->thread_count + 5);
|
char *out_str = (char *) malloc(17 * target->rtos->thread_count + 5);
|
||||||
char* tmp_str = out_str;
|
char *tmp_str = out_str;
|
||||||
tmp_str += sprintf(tmp_str, "m");
|
tmp_str += sprintf(tmp_str, "m");
|
||||||
for (i = 0; i < target->rtos->thread_count; i++) {
|
for (i = 0; i < target->rtos->thread_count; i++) {
|
||||||
if (i != 0) {
|
if (i != 0)
|
||||||
tmp_str += sprintf(tmp_str, ",");
|
tmp_str += sprintf(tmp_str, ",");
|
||||||
}
|
|
||||||
tmp_str += sprintf(tmp_str, "%016" PRIx64,
|
tmp_str += sprintf(tmp_str, "%016" PRIx64,
|
||||||
target->rtos->thread_details[i].threadid);
|
target->rtos->thread_details[i].threadid);
|
||||||
}
|
}
|
||||||
tmp_str[0] = 0;
|
tmp_str[0] = 0;
|
||||||
gdb_put_packet(connection, out_str, strlen(out_str));
|
gdb_put_packet(connection, out_str, strlen(out_str));
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
gdb_put_packet(connection, "", 0);
|
gdb_put_packet(connection, "", 0);
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
} else if (strstr(packet, "qsThreadInfo")) {
|
||||||
else if (strstr(packet, "qsThreadInfo"))
|
|
||||||
{
|
|
||||||
gdb_put_packet(connection, "l", 1);
|
gdb_put_packet(connection, "l", 1);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
} else if (strstr(packet, "qAttached")) {
|
||||||
else if (strstr(packet, "qAttached"))
|
|
||||||
{
|
|
||||||
gdb_put_packet(connection, "1", 1);
|
gdb_put_packet(connection, "1", 1);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
} else if (strstr(packet, "qOffsets")) {
|
||||||
else if (strstr(packet, "qOffsets"))
|
|
||||||
{
|
|
||||||
char offsets[] = "Text=0;Data=0;Bss=0";
|
char offsets[] = "Text=0;Data=0;Bss=0";
|
||||||
gdb_put_packet(connection, offsets, sizeof(offsets)-1);
|
gdb_put_packet(connection, offsets, sizeof(offsets)-1);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
} else if (strstr(packet, "qC")) {
|
||||||
else if (strstr(packet, "qC"))
|
if (target->rtos != NULL) {
|
||||||
{
|
|
||||||
if( target->rtos!=NULL )
|
|
||||||
{
|
|
||||||
char buffer[15];
|
char buffer[15];
|
||||||
int size;
|
int size;
|
||||||
size = snprintf(buffer, 15, "QC%08X", (int)target->rtos->current_thread);
|
size = snprintf(buffer, 15, "QC%08X", (int)target->rtos->current_thread);
|
||||||
gdb_put_packet(connection, buffer, size);
|
gdb_put_packet(connection, buffer, size);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
|
||||||
gdb_put_packet(connection, "QC0", 3);
|
gdb_put_packet(connection, "QC0", 3);
|
||||||
}
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
} else if (packet[0] == 'T') { /* Is thread alive? */
|
||||||
else if ( packet[0] == 'T' ) // Is thread alive?
|
|
||||||
{
|
|
||||||
threadid_t threadid;
|
threadid_t threadid;
|
||||||
int found = -1;
|
int found = -1;
|
||||||
sscanf(packet, "T%" SCNx64, &threadid);
|
sscanf(packet, "T%" SCNx64, &threadid);
|
||||||
if ((target->rtos != NULL) && (target->rtos->thread_details
|
if ((target->rtos != NULL) && (target->rtos->thread_details != NULL)) {
|
||||||
!= NULL)) {
|
|
||||||
int thread_num;
|
int thread_num;
|
||||||
for (thread_num = 0; thread_num
|
for (thread_num = 0; thread_num < target->rtos->thread_count; thread_num++) {
|
||||||
< target->rtos->thread_count; thread_num++) {
|
if (target->rtos->thread_details[thread_num].threadid == threadid) {
|
||||||
if (target->rtos->thread_details[thread_num].threadid
|
if (target->rtos->thread_details[thread_num].exists)
|
||||||
== threadid) {
|
|
||||||
if (target->rtos->thread_details[thread_num].exists) {
|
|
||||||
found = thread_num;
|
found = thread_num;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (found != -1) {
|
if (found != -1)
|
||||||
gdb_put_packet(connection, "OK", 2); // thread alive
|
gdb_put_packet(connection, "OK", 2); /* thread alive */
|
||||||
} else {
|
else
|
||||||
gdb_put_packet(connection, "E01", 3); // thread not found
|
gdb_put_packet(connection, "E01", 3); /* thread not found */
|
||||||
}
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
} else if (packet[0] == 'H') { /* Set current thread ( 'c' for step and continue, 'g' for
|
||||||
else if ( packet[0] == 'H') // Set current thread ( 'c' for step and continue, 'g' for all other operations )
|
* all other operations ) */
|
||||||
{
|
|
||||||
if ((packet[1] == 'g') && (target->rtos != NULL))
|
if ((packet[1] == 'g') && (target->rtos != NULL))
|
||||||
sscanf(packet, "Hg%16" SCNx64, &target->rtos->current_threadid);
|
sscanf(packet, "Hg%16" SCNx64, &target->rtos->current_threadid);
|
||||||
gdb_put_packet(connection, "OK", 2);
|
gdb_put_packet(connection, "OK", 2);
|
||||||
|
@ -420,17 +364,16 @@ int rtos_get_gdb_reg_list(struct connection *connection)
|
||||||
{
|
{
|
||||||
struct target *target = get_target_from_connection(connection);
|
struct target *target = get_target_from_connection(connection);
|
||||||
int64_t current_threadid = target->rtos->current_threadid;
|
int64_t current_threadid = target->rtos->current_threadid;
|
||||||
if ((target->rtos != NULL) &&
|
if ((target->rtos != NULL) && (current_threadid != -1) &&
|
||||||
(current_threadid != -1) &&
|
(current_threadid != 0) &&
|
||||||
(current_threadid != 0) &&
|
((current_threadid != target->rtos->current_thread) ||
|
||||||
((current_threadid != target->rtos->current_thread) ||
|
(target->smp))) { /* in smp several current thread are possible */
|
||||||
(target->smp))) /* in smp several current thread are possible */
|
char *hex_reg_list;
|
||||||
{
|
target->rtos->type->get_thread_reg_list(target->rtos,
|
||||||
char * hex_reg_list;
|
current_threadid,
|
||||||
target->rtos->type->get_thread_reg_list( target->rtos, current_threadid, &hex_reg_list );
|
&hex_reg_list);
|
||||||
|
|
||||||
if ( hex_reg_list != NULL )
|
if (hex_reg_list != NULL) {
|
||||||
{
|
|
||||||
gdb_put_packet(connection, hex_reg_list, strlen(hex_reg_list));
|
gdb_put_packet(connection, hex_reg_list, strlen(hex_reg_list));
|
||||||
free(hex_reg_list);
|
free(hex_reg_list);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -439,103 +382,84 @@ int rtos_get_gdb_reg_list(struct connection *connection)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rtos_generic_stack_read(struct target *target,
|
||||||
|
const struct rtos_register_stacking *stacking,
|
||||||
int rtos_generic_stack_read( struct target * target, const struct rtos_register_stacking* stacking, int64_t stack_ptr, char ** hex_reg_list )
|
int64_t stack_ptr,
|
||||||
|
char **hex_reg_list)
|
||||||
{
|
{
|
||||||
int list_size = 0;
|
int list_size = 0;
|
||||||
char * tmp_str_ptr;
|
char *tmp_str_ptr;
|
||||||
int64_t new_stack_ptr;
|
int64_t new_stack_ptr;
|
||||||
int i;
|
int i;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if ( stack_ptr == 0)
|
if (stack_ptr == 0) {
|
||||||
{
|
|
||||||
LOG_OUTPUT("Error: null stack pointer in thread\r\n");
|
LOG_OUTPUT("Error: null stack pointer in thread\r\n");
|
||||||
return -5;
|
return -5;
|
||||||
}
|
}
|
||||||
// Read the stack
|
/* Read the stack */
|
||||||
uint8_t * stack_data = (uint8_t*) malloc( stacking->stack_registers_size );
|
uint8_t *stack_data = (uint8_t *) malloc(stacking->stack_registers_size);
|
||||||
uint32_t address = stack_ptr;
|
uint32_t address = stack_ptr;
|
||||||
|
|
||||||
if ( stacking->stack_growth_direction == 1 )
|
if (stacking->stack_growth_direction == 1)
|
||||||
{
|
address -= stacking->stack_registers_size;
|
||||||
address -= stacking->stack_registers_size;
|
retval = target_read_buffer(target, address, stacking->stack_registers_size, stack_data);
|
||||||
}
|
if (retval != ERROR_OK) {
|
||||||
retval = target_read_buffer( target, address, stacking->stack_registers_size, stack_data);
|
|
||||||
if ( retval != ERROR_OK )
|
|
||||||
{
|
|
||||||
LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
|
LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
/*
|
#if 0
|
||||||
LOG_OUTPUT("Stack Data :");
|
LOG_OUTPUT("Stack Data :");
|
||||||
for(i = 0; i < stacking->stack_registers_size; i++ )
|
for (i = 0; i < stacking->stack_registers_size; i++)
|
||||||
{
|
LOG_OUTPUT("%02X", stack_data[i]);
|
||||||
LOG_OUTPUT("%02X",stack_data[i]);
|
LOG_OUTPUT("\r\n");
|
||||||
}
|
#endif
|
||||||
LOG_OUTPUT("\r\n");
|
for (i = 0; i < stacking->num_output_registers; i++)
|
||||||
*/
|
|
||||||
for( i = 0; i < stacking->num_output_registers; i++ )
|
|
||||||
{
|
|
||||||
list_size += stacking->register_offsets[i].width_bits/8;
|
list_size += stacking->register_offsets[i].width_bits/8;
|
||||||
}
|
*hex_reg_list = (char *)malloc(list_size*2 + 1);
|
||||||
*hex_reg_list = (char*)malloc( list_size*2 +1 );
|
|
||||||
tmp_str_ptr = *hex_reg_list;
|
tmp_str_ptr = *hex_reg_list;
|
||||||
new_stack_ptr = stack_ptr - stacking->stack_growth_direction * stacking->stack_registers_size;
|
new_stack_ptr = stack_ptr - stacking->stack_growth_direction *
|
||||||
|
stacking->stack_registers_size;
|
||||||
if (stacking->stack_alignment != 0) {
|
if (stacking->stack_alignment != 0) {
|
||||||
/* Align new stack pointer to x byte boundary */
|
/* Align new stack pointer to x byte boundary */
|
||||||
new_stack_ptr =
|
new_stack_ptr =
|
||||||
(new_stack_ptr & (~((int64_t) stacking->stack_alignment - 1))) +
|
(new_stack_ptr & (~((int64_t) stacking->stack_alignment - 1))) +
|
||||||
((stacking->stack_growth_direction == -1) ? stacking->stack_alignment : 0);
|
((stacking->stack_growth_direction == -1) ? stacking->stack_alignment : 0);
|
||||||
}
|
}
|
||||||
for( i = 0; i < stacking->num_output_registers; i++ )
|
for (i = 0; i < stacking->num_output_registers; i++) {
|
||||||
{
|
|
||||||
int j;
|
int j;
|
||||||
for ( j = 0; j < stacking->register_offsets[i].width_bits/8; j++ )
|
for (j = 0; j < stacking->register_offsets[i].width_bits/8; j++) {
|
||||||
{
|
if (stacking->register_offsets[i].offset == -1)
|
||||||
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", 0 );
|
tmp_str_ptr += sprintf(tmp_str_ptr, "%02x",
|
||||||
}
|
((uint8_t *)&new_stack_ptr)[j]);
|
||||||
else if ( stacking->register_offsets[i].offset == -2 )
|
|
||||||
{
|
|
||||||
tmp_str_ptr += sprintf( tmp_str_ptr, "%02x", ((uint8_t*)&new_stack_ptr)[j] );
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
tmp_str_ptr += sprintf(tmp_str_ptr, "%02x",
|
||||||
tmp_str_ptr += sprintf( tmp_str_ptr,"%02x", stack_data[ stacking->register_offsets[i].offset + j ] );
|
stack_data[stacking->register_offsets[i].offset + j]);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// LOG_OUTPUT("Output register string: %s\r\n", *hex_reg_list);
|
/* LOG_OUTPUT("Output register string: %s\r\n", *hex_reg_list); */
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rtos_try_next( struct target * target )
|
int rtos_try_next(struct target *target)
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
if ( target->rtos == NULL )
|
if (target->rtos == NULL)
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
for (x = 0 ; rtos_types[x] ; x++) {
|
for (x = 0; rtos_types[x]; x++) {
|
||||||
if (target->rtos->type == rtos_types[x] ) {
|
if (target->rtos->type == rtos_types[x]) {
|
||||||
/* found */
|
/* found */
|
||||||
if ( rtos_types[x+1] != NULL )
|
if (rtos_types[x+1] != NULL) {
|
||||||
{
|
|
||||||
target->rtos->type = rtos_types[x+1];
|
target->rtos->type = rtos_types[x+1];
|
||||||
if ( target->rtos->symbols != NULL )
|
if (target->rtos->symbols != NULL)
|
||||||
{
|
free(target->rtos->symbols);
|
||||||
free( target->rtos->symbols );
|
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
} else {
|
||||||
else
|
/* No more rtos types */
|
||||||
{
|
|
||||||
// No more rtos types
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -545,24 +469,23 @@ int rtos_try_next( struct target * target )
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hex_to_str( char* dst, char * hex_src )
|
static void hex_to_str(char *dst, char *hex_src)
|
||||||
{
|
{
|
||||||
int src_pos = 0;
|
int src_pos = 0;
|
||||||
int dst_pos = 0;
|
int dst_pos = 0;
|
||||||
|
|
||||||
while ( hex_src[src_pos] != '\x00' )
|
while (hex_src[src_pos] != '\x00') {
|
||||||
{
|
|
||||||
char hex_char = hex_src[src_pos];
|
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';
|
char hex_digit_val =
|
||||||
if ( 0 == (src_pos & 0x01) )
|
(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] = hex_digit_val;
|
||||||
dst[dst_pos+1] = 0;
|
dst[dst_pos+1] = 0;
|
||||||
}
|
} else {
|
||||||
else
|
((unsigned char *)dst)[dst_pos] <<= 4;
|
||||||
{
|
((unsigned char *)dst)[dst_pos] += hex_digit_val;
|
||||||
((unsigned char*)dst)[dst_pos] <<= 4;
|
|
||||||
((unsigned char*)dst)[dst_pos] += hex_digit_val;
|
|
||||||
dst_pos++;
|
dst_pos++;
|
||||||
}
|
}
|
||||||
src_pos++;
|
src_pos++;
|
||||||
|
@ -572,21 +495,16 @@ static void hex_to_str( char* dst, char * hex_src )
|
||||||
|
|
||||||
int str_to_hex(char *hex_dst, char *src)
|
int str_to_hex(char *hex_dst, char *src)
|
||||||
{
|
{
|
||||||
char * posptr = hex_dst;
|
char *posptr = hex_dst;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
for( i = 0; i < strlen(src); i++)
|
for (i = 0; i < strlen(src); i++)
|
||||||
{
|
posptr += sprintf(posptr, "%02x", (unsigned char)src[i]);
|
||||||
posptr += sprintf( posptr, "%02x", (unsigned char)src[i] );
|
return posptr - hex_dst;
|
||||||
}
|
|
||||||
return (posptr-hex_dst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rtos_update_threads(struct target *target)
|
||||||
int rtos_update_threads( struct target* target )
|
|
||||||
{
|
{
|
||||||
if ((target->rtos != NULL) && (target->rtos->type != NULL))
|
if ((target->rtos != NULL) && (target->rtos->type != NULL))
|
||||||
{
|
|
||||||
target->rtos->type->update_threads(target->rtos);
|
target->rtos->type->update_threads(target->rtos);
|
||||||
}
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
#ifndef RTOS_H
|
#ifndef RTOS_H
|
||||||
#define RTOS_H
|
#define RTOS_H
|
||||||
|
|
||||||
|
|
||||||
#include "server/server.h"
|
#include "server/server.h"
|
||||||
#include <helper/types.h>
|
#include <helper/types.h>
|
||||||
#include <jim-nvp.h>
|
#include <jim-nvp.h>
|
||||||
|
@ -34,83 +33,75 @@ struct reg;
|
||||||
/**
|
/**
|
||||||
* Table should be terminated by an element with NULL in symbol_name
|
* Table should be terminated by an element with NULL in symbol_name
|
||||||
*/
|
*/
|
||||||
typedef struct symbol_table_elem_struct
|
typedef struct symbol_table_elem_struct {
|
||||||
{
|
char *symbol_name;
|
||||||
char * symbol_name;
|
|
||||||
symbol_address_t address;
|
symbol_address_t address;
|
||||||
|
|
||||||
} symbol_table_elem_t;
|
} symbol_table_elem_t;
|
||||||
|
|
||||||
struct thread_detail
|
struct thread_detail {
|
||||||
{
|
|
||||||
threadid_t threadid;
|
threadid_t threadid;
|
||||||
bool exists;
|
bool exists;
|
||||||
char * display_str;
|
char *display_str;
|
||||||
char * thread_name_str;
|
char *thread_name_str;
|
||||||
char * extra_info_str;
|
char *extra_info_str;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rtos
|
struct rtos {
|
||||||
{
|
|
||||||
const struct rtos_type *type;
|
const struct rtos_type *type;
|
||||||
|
|
||||||
|
symbol_table_elem_t *symbols;
|
||||||
symbol_table_elem_t * symbols;
|
|
||||||
struct target *target;
|
struct target *target;
|
||||||
/* add a context variable instead of global variable */
|
/* add a context variable instead of global variable */
|
||||||
int64_t current_threadid;
|
int64_t current_threadid;
|
||||||
threadid_t current_thread;
|
threadid_t current_thread;
|
||||||
struct thread_detail* thread_details;
|
struct thread_detail *thread_details;
|
||||||
int thread_count;
|
int thread_count;
|
||||||
int (*gdb_thread_packet)(struct connection *connection, char *packet, int packet_size);
|
int (*gdb_thread_packet)(struct connection *connection, char *packet, int packet_size);
|
||||||
void * rtos_specific_params;
|
void *rtos_specific_params;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct rtos_type {
|
||||||
|
char *name;
|
||||||
struct rtos_type
|
int (*detect_rtos)(struct target *target);
|
||||||
{
|
int (*create)(struct target *target);
|
||||||
char * name;
|
|
||||||
int (*detect_rtos) ( struct target* target );
|
|
||||||
int (*create) ( struct target* target );
|
|
||||||
int (*smp_init)(struct target *target);
|
int (*smp_init)(struct target *target);
|
||||||
int (*update_threads) ( struct rtos* rtos );
|
int (*update_threads)(struct rtos *rtos);
|
||||||
int (*get_thread_reg_list) ( struct rtos *rtos, int64_t thread_id, char ** hex_reg_list );
|
int (*get_thread_reg_list)(struct rtos *rtos, int64_t thread_id, char **hex_reg_list);
|
||||||
int (*get_symbol_list_to_lookup) (symbol_table_elem_t * symbol_list[] );
|
int (*get_symbol_list_to_lookup)(symbol_table_elem_t *symbol_list[]);
|
||||||
int (*clean)(struct target *target);
|
int (*clean)(struct target *target);
|
||||||
char * (*ps_command)(struct target *target);
|
char * (*ps_command)(struct target *target);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct stack_register_offset {
|
||||||
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
|
||||||
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
|
* stack pointer register */
|
||||||
unsigned short width_bits;
|
unsigned short width_bits;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rtos_register_stacking
|
struct rtos_register_stacking {
|
||||||
{
|
unsigned char stack_registers_size;
|
||||||
unsigned char stack_registers_size;
|
signed char stack_growth_direction;
|
||||||
signed char stack_growth_direction;
|
unsigned char num_output_registers;
|
||||||
unsigned char num_output_registers;
|
unsigned char stack_alignment;
|
||||||
unsigned char stack_alignment;
|
const struct stack_register_offset *register_offsets;
|
||||||
const struct stack_register_offset* register_offsets;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GDB_THREAD_PACKET_NOT_CONSUMED (-40)
|
#define GDB_THREAD_PACKET_NOT_CONSUMED (-40)
|
||||||
|
|
||||||
int rtos_create(Jim_GetOptInfo *goi, struct target * target);
|
int rtos_create(Jim_GetOptInfo *goi, struct target *target);
|
||||||
int rtos_generic_stack_read( struct target * target, const struct rtos_register_stacking* stacking, int64_t stack_ptr, char ** hex_reg_list );
|
int rtos_generic_stack_read(struct target *target,
|
||||||
int rtos_try_next( struct target * target );
|
const struct rtos_register_stacking *stacking,
|
||||||
|
int64_t stack_ptr,
|
||||||
|
char **hex_reg_list);
|
||||||
|
int rtos_try_next(struct target *target);
|
||||||
int gdb_thread_packet(struct connection *connection, char *packet, int packet_size);
|
int gdb_thread_packet(struct connection *connection, char *packet, int packet_size);
|
||||||
int rtos_get_gdb_reg_list(struct connection *connection);
|
int rtos_get_gdb_reg_list(struct connection *connection);
|
||||||
int rtos_update_threads( struct target *target );
|
int rtos_update_threads(struct target *target);
|
||||||
int rtos_smp_init(struct target *target);
|
int rtos_smp_init(struct target *target);
|
||||||
/* function for handling symbol access */
|
/* function for handling symbol access */
|
||||||
int rtos_qsymbol(struct connection *connection, char *packet, int packet_size);
|
int rtos_qsymbol(struct connection *connection, char *packet, int packet_size);
|
||||||
int str_to_hex(char *hex_dst, char *src);
|
int str_to_hex(char *hex_dst, char *src);
|
||||||
|
|
||||||
#endif // RTOS_H
|
#endif /* RTOS_H */
|
||||||
|
|
|
@ -23,42 +23,38 @@
|
||||||
#include "rtos.h"
|
#include "rtos.h"
|
||||||
|
|
||||||
static const struct stack_register_offset rtos_eCos_Cortex_M3_stack_offsets[] = {
|
static const struct stack_register_offset rtos_eCos_Cortex_M3_stack_offsets[] = {
|
||||||
{ 0x0c, 32 }, /* r0 */
|
{ 0x0c, 32 }, /* r0 */
|
||||||
{ 0x10, 32 }, /* r1 */
|
{ 0x10, 32 }, /* r1 */
|
||||||
{ 0x14, 32 }, /* r2 */
|
{ 0x14, 32 }, /* r2 */
|
||||||
{ 0x18, 32 }, /* r3 */
|
{ 0x18, 32 }, /* r3 */
|
||||||
{ 0x1c, 32 }, /* r4 */
|
{ 0x1c, 32 }, /* r4 */
|
||||||
{ 0x20, 32 }, /* r5 */
|
{ 0x20, 32 }, /* r5 */
|
||||||
{ 0x24, 32 }, /* r6 */
|
{ 0x24, 32 }, /* r6 */
|
||||||
{ 0x28, 32 }, /* r7 */
|
{ 0x28, 32 }, /* r7 */
|
||||||
{ 0x2c, 32 }, /* r8 */
|
{ 0x2c, 32 }, /* r8 */
|
||||||
{ 0x30, 32 }, /* r9 */
|
{ 0x30, 32 }, /* r9 */
|
||||||
{ 0x34, 32 }, /* r10 */
|
{ 0x34, 32 }, /* r10 */
|
||||||
{ 0x38, 32 }, /* r11 */
|
{ 0x38, 32 }, /* r11 */
|
||||||
{ 0x3c, 32 }, /* r12 */
|
{ 0x3c, 32 }, /* r12 */
|
||||||
{ -2, 32 }, /* sp */
|
{ -2, 32 }, /* sp */
|
||||||
{ -1, 32 }, /* lr */
|
{ -1, 32 }, /* lr */
|
||||||
{ 0x40, 32 }, /* pc */
|
{ 0x40, 32 }, /* pc */
|
||||||
{ -1, 96 }, /* FPA1 */
|
{ -1, 96 }, /* FPA1 */
|
||||||
{ -1, 96 }, /* FPA2 */
|
{ -1, 96 }, /* FPA2 */
|
||||||
{ -1, 96 }, /* FPA3 */
|
{ -1, 96 }, /* FPA3 */
|
||||||
{ -1, 96 }, /* FPA4 */
|
{ -1, 96 }, /* FPA4 */
|
||||||
{ -1, 96 }, /* FPA5 */
|
{ -1, 96 }, /* FPA5 */
|
||||||
{ -1, 96 }, /* FPA6 */
|
{ -1, 96 }, /* FPA6 */
|
||||||
{ -1, 96 }, /* FPA7 */
|
{ -1, 96 }, /* FPA7 */
|
||||||
{ -1, 96 }, /* FPA8 */
|
{ -1, 96 }, /* FPA8 */
|
||||||
{ -1, 32 }, /* FPS */
|
{ -1, 32 }, /* FPS */
|
||||||
{ -1, 32 }, /* xPSR */
|
{ -1, 32 }, /* xPSR */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const struct rtos_register_stacking rtos_eCos_Cortex_M3_stacking = {
|
||||||
const struct rtos_register_stacking rtos_eCos_Cortex_M3_stacking =
|
0x44, /* stack_registers_size */
|
||||||
{
|
-1, /* stack_growth_direction */
|
||||||
0x44, /* stack_registers_size */
|
26, /* num_output_registers */
|
||||||
-1, /* stack_growth_direction */
|
8, /* stack_alignment */
|
||||||
26, /* num_output_registers */
|
rtos_eCos_Cortex_M3_stack_offsets /* register_offsets */
|
||||||
8, /* stack_alignment */
|
|
||||||
rtos_eCos_Cortex_M3_stack_offsets /* register_offsets */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -27,4 +27,4 @@
|
||||||
|
|
||||||
extern const struct rtos_register_stacking rtos_eCos_Cortex_M3_stacking;
|
extern const struct rtos_register_stacking rtos_eCos_Cortex_M3_stacking;
|
||||||
|
|
||||||
#endif //ifndef INCLUDED_RTOS_STANDARD_STACKINGS_H_
|
#endif /* ifndef INCLUDED_RTOS_STANDARD_STACKINGS_H_ */
|
||||||
|
|
|
@ -25,42 +25,38 @@
|
||||||
#include "rtos.h"
|
#include "rtos.h"
|
||||||
|
|
||||||
static const struct stack_register_offset rtos_standard_Cortex_M3_stack_offsets[] = {
|
static const struct stack_register_offset rtos_standard_Cortex_M3_stack_offsets[] = {
|
||||||
{ 0x20, 32 }, /* r0 */
|
{ 0x20, 32 }, /* r0 */
|
||||||
{ 0x24, 32 }, /* r1 */
|
{ 0x24, 32 }, /* r1 */
|
||||||
{ 0x28, 32 }, /* r2 */
|
{ 0x28, 32 }, /* r2 */
|
||||||
{ 0x2c, 32 }, /* r3 */
|
{ 0x2c, 32 }, /* r3 */
|
||||||
{ 0x00, 32 }, /* r4 */
|
{ 0x00, 32 }, /* r4 */
|
||||||
{ 0x04, 32 }, /* r5 */
|
{ 0x04, 32 }, /* r5 */
|
||||||
{ 0x08, 32 }, /* r6 */
|
{ 0x08, 32 }, /* r6 */
|
||||||
{ 0x0c, 32 }, /* r7 */
|
{ 0x0c, 32 }, /* r7 */
|
||||||
{ 0x10, 32 }, /* r8 */
|
{ 0x10, 32 }, /* r8 */
|
||||||
{ 0x14, 32 }, /* r9 */
|
{ 0x14, 32 }, /* r9 */
|
||||||
{ 0x18, 32 }, /* r10 */
|
{ 0x18, 32 }, /* r10 */
|
||||||
{ 0x1c, 32 }, /* r11 */
|
{ 0x1c, 32 }, /* r11 */
|
||||||
{ 0x30, 32 }, /* r12 */
|
{ 0x30, 32 }, /* r12 */
|
||||||
{ -2, 32 }, /* sp */
|
{ -2, 32 }, /* sp */
|
||||||
{ 0x34, 32 }, /* lr */
|
{ 0x34, 32 }, /* lr */
|
||||||
{ 0x38, 32 }, /* pc */
|
{ 0x38, 32 }, /* pc */
|
||||||
{ -1, 96 }, /* FPA1 */
|
{ -1, 96 }, /* FPA1 */
|
||||||
{ -1, 96 }, /* FPA2 */
|
{ -1, 96 }, /* FPA2 */
|
||||||
{ -1, 96 }, /* FPA3 */
|
{ -1, 96 }, /* FPA3 */
|
||||||
{ -1, 96 }, /* FPA4 */
|
{ -1, 96 }, /* FPA4 */
|
||||||
{ -1, 96 }, /* FPA5 */
|
{ -1, 96 }, /* FPA5 */
|
||||||
{ -1, 96 }, /* FPA6 */
|
{ -1, 96 }, /* FPA6 */
|
||||||
{ -1, 96 }, /* FPA7 */
|
{ -1, 96 }, /* FPA7 */
|
||||||
{ -1, 96 }, /* FPA8 */
|
{ -1, 96 }, /* FPA8 */
|
||||||
{ -1, 32 }, /* FPS */
|
{ -1, 32 }, /* FPS */
|
||||||
{ 0x3c, 32 }, /* xPSR */
|
{ 0x3c, 32 }, /* xPSR */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const struct rtos_register_stacking rtos_standard_Cortex_M3_stacking = {
|
||||||
const struct rtos_register_stacking rtos_standard_Cortex_M3_stacking =
|
0x40, /* stack_registers_size */
|
||||||
{
|
-1, /* stack_growth_direction */
|
||||||
0x40, /* stack_registers_size */
|
26, /* num_output_registers */
|
||||||
-1, /* stack_growth_direction */
|
8, /* stack_alignment */
|
||||||
26, /* num_output_registers */
|
rtos_standard_Cortex_M3_stack_offsets /* register_offsets */
|
||||||
8, /* stack_alignment */
|
|
||||||
rtos_standard_Cortex_M3_stack_offsets /* register_offsets */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,4 +29,4 @@
|
||||||
|
|
||||||
extern const struct rtos_register_stacking rtos_standard_Cortex_M3_stacking;
|
extern const struct rtos_register_stacking rtos_standard_Cortex_M3_stacking;
|
||||||
|
|
||||||
#endif //ifndef INCLUDED_RTOS_STANDARD_STACKINGS_H_
|
#endif /* ifndef INCLUDED_RTOS_STANDARD_STACKINGS_H_ */
|
||||||
|
|
Loading…
Reference in New Issue