This is an automated email from Gerrit. Vlad Ivanov (vlad@ivanov.email) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/4486
-- gerrit commit 401842e04dcff12afbc0e5a0247c34675f29ff35 Author: Vlad Ivanov <vlad@ivanov.email> Date: Mon Apr 9 06:12:40 2018 -0400 Implement serdes_print_struct and RTOS conf listing Change-Id: Ic90bc275d177bd9c70f64560ed2610a6dfc1b645 Signed-off-by: Vlad Ivanov <vlad@ivanov.email> diff --git a/src/helper/serdes.c b/src/helper/serdes.c index e992587..acfc7db 100644 --- a/src/helper/serdes.c +++ b/src/helper/serdes.c @@ -25,8 +25,51 @@ #include "log.h" #include "serdes.h" +union value_target { + void *data; + uint8_t *data_uint8; + int8_t *data_int8; + uint32_t *data_uint32; + int32_t *data_int32; +}; + +static char *string_trim(const char *str, size_t in_length, + size_t *out_length) { + size_t pos = 0; + size_t last_char = 0; + size_t result_length = strnlen(str, in_length); + char *result = calloc(result_length, 1); + bool started = false; + + for (size_t i = 0; i < result_length; i++) { + if (!started) { + if (str[i] != ' ') { + started = true; + result[pos] = str[i]; + last_char = pos; + pos++; + } + } else { + result[pos] = str[i]; + pos++; + + if (str[i] != ' ') { + last_char = pos; + } + } + } + + result[last_char] = '\0'; + + if (out_length) { + *out_length = last_char; + } + + return result; +} + static int read_value(Jim_Interp *interp, Jim_Obj *value, - const struct serdes_field *field, void *storage) + enum serdes_type type, void *storage) { static struct { jim_wide lower; @@ -38,7 +81,7 @@ static int read_value(Jim_Interp *interp, Jim_Obj *value, [serdes_int32] = { INT32_MIN, INT32_MAX }, }; - switch (field->type) { + switch (type) { case serdes_uint8: case serdes_int8: case serdes_uint32: @@ -51,36 +94,30 @@ static int read_value(Jim_Interp *interp, Jim_Obj *value, return ERROR_FAIL; } - upper_limit = number_limits[field->type].upper; - lower_limit = number_limits[field->type].lower; + upper_limit = number_limits[type].upper; + lower_limit = number_limits[type].lower; if (wide > upper_limit || wide < lower_limit) { LOG_ERROR("serdes: value %" JIM_WIDE_MODIFIER " is out of range", wide); return ERROR_FAIL; } - union { - void * data; - uint8_t * data_uint8; - int8_t * data_int8; - uint32_t * data_uint32; - int32_t * data_int32; - } target = { + union value_target target = { .data = storage }; - switch (field->type) { + switch (type) { case serdes_uint8: - * target.data_uint8 = wide; + *target.data_uint8 = wide; break; case serdes_int8: - * target.data_int8 = wide; + *target.data_int8 = wide; break; case serdes_uint32: - * target.data_uint32 = wide; + *target.data_uint32 = wide; break; case serdes_int32: - * target.data_int32 = wide; + *target.data_int32 = wide; break; default: return ERROR_FAIL; @@ -110,8 +147,42 @@ static int read_value(Jim_Interp *interp, Jim_Obj *value, return ERROR_OK; } +static int print_value(const struct serdes_field *field, void *storage) +{ + union value_target target = { + .data = storage + }; + + fprintf(stderr, "\t.%s = ", field->name); + + switch (field->type) { + case serdes_int8: + fprintf(stderr, "%" PRId8 ",", *target.data_int8); + break; + case serdes_uint8: + fprintf(stderr, "%" PRIu8 ",", *target.data_uint8); + break; + case serdes_int32: + fprintf(stderr, "%" PRId32 ",", *target.data_int32); + break; + case serdes_uint32: + fprintf(stderr, "%" PRIu32 ",", *target.data_uint32); + break; + case serdes_string: + fprintf(stderr, "%s", *(const char **) target.data); + break; + default: + return ERROR_FAIL; + } + + fprintf(stderr, "\n"); + + return ERROR_OK; +} + int serdes_read_struct(Jim_Interp *interp, Jim_Obj **objects, - const struct serdes_field *fields, void *storage) + const struct serdes_field *fields, const struct serdes_wordset *wordset, + void *storage) { int result = ERROR_FAIL; @@ -120,21 +191,67 @@ int serdes_read_struct(Jim_Interp *interp, Jim_Obj **objects, } const struct serdes_field *field; + Jim_Obj **object = objects; + char *key_trimmed = NULL; - // Skip first key - objects += 1; field = fields; - for (; field->offset != -1; field++, objects += 2) { - Jim_Obj *object = objects[0]; - void * target = (void *) ((uintptr_t) storage + (uintptr_t) field->offset); + for (; field->offset != -1; field++) { + int len = 0; + size_t key_trimmed_length = 0; + const char *key_string = Jim_GetString(*object, &len); - if (read_value(interp, object, field, target) != ERROR_OK) { + key_trimmed = string_trim(key_string, len, &key_trimmed_length); + void *key = wordset->check(key_trimmed, key_trimmed_length); + + if (!key) { + LOG_ERROR("Unknown struct field: %s", key_trimmed); goto error; } + + object++; + + size_t index = wordset->value(key); + void *target = (void *) ((uintptr_t) storage + + (uintptr_t) fields[index].offset); + + if (read_value(interp, *object, + fields[index].type, target) != ERROR_OK) { + goto error; + } + + object++; } result = ERROR_OK; error: + if (key_trimmed) { + free(key_trimmed); + } + + return result; +} + +int serdes_print_struct(const struct serdes_field *fields, void *storage) +{ + int result = ERROR_FAIL; + + if (fields == NULL) { + goto error; + } + + const struct serdes_field *field = fields; + + fprintf(stderr, "{\n"); + + for (; field->offset != -1; field++) { + void *target = (void *) ((uintptr_t) storage + (uintptr_t) field->offset); + print_value(field, target); + } + + fprintf(stderr, "}\n"); + + result = ERROR_OK; +error: return result; } diff --git a/src/helper/serdes.h b/src/helper/serdes.h index 9d615bd..e8e330c 100644 --- a/src/helper/serdes.h +++ b/src/helper/serdes.h @@ -33,9 +33,24 @@ enum serdes_type { struct serdes_field { enum serdes_type type; off_t offset; + const char * name; }; +typedef void * (* serdes_check_fn_t)(const char *text, size_t len); +typedef int (* serdes_value_fn_t)(void *result); + +struct serdes_wordset { + serdes_check_fn_t check; + serdes_value_fn_t value; +}; + +#define SERDES_FIELD(type, base_type, name) \ + { (type), offsetof(base_type, name), (#name) } + int serdes_read_struct(Jim_Interp *interp, Jim_Obj **objects, - const struct serdes_field *fields, void *storage); + const struct serdes_field *fields, const struct serdes_wordset *wordset, + void *storage); + +int serdes_print_struct(const struct serdes_field *fields, void *storage); #endif /* OPENOCD_HELPER_SERDES_H */ diff --git a/src/rtos/FreeRTOS.c b/src/rtos/FreeRTOS.c index 33328b2..440ebff 100644 --- a/src/rtos/FreeRTOS.c +++ b/src/rtos/FreeRTOS.c @@ -21,6 +21,7 @@ #endif #include <helper/time_support.h> +#include <helper/list.h> #include <jtag/jtag.h> #include "target/target.h" #include "target/target_type.h" @@ -35,9 +36,8 @@ #define FREERTOS_MAX_PRIORITIES 63 -#define FreeRTOS_STRUCT(int_type, ptr_type, list_prev_offset) - struct FreeRTOS_params { + struct list_head list; const char *target_name; const unsigned char thread_count_width; const unsigned char pointer_width; @@ -52,52 +52,20 @@ struct FreeRTOS_params { const struct rtos_register_stacking *stacking_info_cm4f_fpu; }; -static const struct FreeRTOS_params FreeRTOS_params_list[] = { - { - "cortex_m", /* target_name */ - 4, /* thread_count_width; */ - 4, /* pointer_width; */ - 16, /* list_next_offset; */ - 20, /* list_width; */ - 8, /* list_elem_next_offset; */ - 12, /* list_elem_content_offset */ - 0, /* thread_stack_offset; */ - 52, /* thread_name_offset; */ - &rtos_standard_Cortex_M3_stacking, /* stacking_info */ - &rtos_standard_Cortex_M4F_stacking, - &rtos_standard_Cortex_M4F_FPU_stacking, - }, - { - "hla_target", /* target_name */ - 4, /* thread_count_width; */ - 4, /* pointer_width; */ - 16, /* list_next_offset; */ - 20, /* list_width; */ - 8, /* list_elem_next_offset; */ - 12, /* list_elem_content_offset */ - 0, /* thread_stack_offset; */ - 52, /* thread_name_offset; */ - &rtos_standard_Cortex_M3_stacking, /* stacking_info */ - &rtos_standard_Cortex_M4F_stacking, - &rtos_standard_Cortex_M4F_FPU_stacking, - }, - { - "nds32_v3", /* target_name */ - 4, /* thread_count_width; */ - 4, /* pointer_width; */ - 16, /* list_next_offset; */ - 20, /* list_width; */ - 8, /* list_elem_next_offset; */ - 12, /* list_elem_content_offset */ - 0, /* thread_stack_offset; */ - 52, /* thread_name_offset; */ - &rtos_standard_NDS32_N1068_stacking, /* stacking_info */ - &rtos_standard_Cortex_M4F_stacking, - &rtos_standard_Cortex_M4F_FPU_stacking, - }, +static const struct serdes_field freertos_params_fields[] = { + SERDES_FIELD(serdes_string, struct FreeRTOS_params, target_name), + SERDES_FIELD(serdes_uint8, struct FreeRTOS_params, thread_count_width), + SERDES_FIELD(serdes_uint8, struct FreeRTOS_params, pointer_width), + SERDES_FIELD(serdes_uint8, struct FreeRTOS_params, list_next_offset), + SERDES_FIELD(serdes_uint8, struct FreeRTOS_params, list_width), + SERDES_FIELD(serdes_uint8, struct FreeRTOS_params, list_elem_next_offset), + SERDES_FIELD(serdes_uint8, struct FreeRTOS_params, list_elem_content_offset), + SERDES_FIELD(serdes_uint8, struct FreeRTOS_params, thread_stack_offset), + SERDES_FIELD(serdes_uint8, struct FreeRTOS_params, thread_name_offset), + { 0, -1 } }; -#define FREERTOS_NUM_PARAMS ((int)(sizeof(FreeRTOS_params_list)/sizeof(struct FreeRTOS_params))) +static LIST_HEAD(freertos_params_list); static bool FreeRTOS_detect_rtos(struct target *target); static int FreeRTOS_create(struct target *target); @@ -105,6 +73,7 @@ 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_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]); static int FreeRTOS_conf_add(Jim_Interp *interp, Jim_Obj **elements, int count); +static int FreeRTOS_conf_list(void); struct rtos_type FreeRTOS_rtos = { .name = "FreeRTOS", @@ -115,6 +84,7 @@ struct rtos_type FreeRTOS_rtos = { .get_thread_reg_list = FreeRTOS_get_thread_reg_list, .get_symbol_list_to_lookup = FreeRTOS_get_symbol_list_to_lookup, .conf_add = FreeRTOS_conf_add, + .conf_list = FreeRTOS_conf_list, }; enum FreeRTOS_symbol_values { @@ -542,47 +512,65 @@ static bool FreeRTOS_detect_rtos(struct target *target) static int FreeRTOS_create(struct target *target) { - int i = 0; - while ((i < FREERTOS_NUM_PARAMS) && - (0 != strcmp(FreeRTOS_params_list[i].target_name, target->type->name))) { - i++; + struct FreeRTOS_params *param; + bool found = false; + + list_for_each_entry(param, &freertos_params_list, list) { + if (strcmp(param->target_name, target->type->name) == 0) { + found = true; + break; + } } - if (i >= FREERTOS_NUM_PARAMS) { + + if (!found) { LOG_ERROR("Could not find target in FreeRTOS compatibility list"); - return -1; + return ERROR_FAIL; } - target->rtos->rtos_specific_params = (void *) &FreeRTOS_params_list[i]; - return 0; + target->rtos->rtos_specific_params = param; + + return ERROR_OK; +} + +static int FreeRTOS_conf_list(void) { + struct FreeRTOS_params *param; + + list_for_each_entry(param, &freertos_params_list, list) { + serdes_print_struct(freertos_params_fields, param); + } + + return ERROR_OK; +} + +static int FreeRTOS_wordset_value(struct freertos_lookup_entry *entry) { + return entry->option; } static int FreeRTOS_conf_add(Jim_Interp *interp, Jim_Obj **elements, int count) { - static const struct serdes_field fields[] = { - { serdes_string, offsetof(struct FreeRTOS_params, target_name) }, - { serdes_uint8, offsetof(struct FreeRTOS_params, thread_count_width) }, - { serdes_uint8, offsetof(struct FreeRTOS_params, pointer_width) }, - { serdes_uint8, offsetof(struct FreeRTOS_params, list_next_offset) }, - { serdes_uint8, offsetof(struct FreeRTOS_params, list_width) }, - { serdes_uint8, offsetof(struct FreeRTOS_params, list_elem_next_offset) }, - { serdes_uint8, offsetof(struct FreeRTOS_params, list_elem_content_offset) }, - { serdes_uint8, offsetof(struct FreeRTOS_params, thread_stack_offset) }, - { serdes_uint8, offsetof(struct FreeRTOS_params, thread_name_offset) }, - { 0, -1 } - }; - - struct FreeRTOS_params params; + struct FreeRTOS_params *params; int result = ERROR_FAIL; + params = calloc(1, sizeof(struct FreeRTOS_params)); + if (count != freertos_option_count * 2) { LOG_ERROR("freertos: invalid number of elements in configuration"); + goto error; } - if (serdes_read_struct(interp, elements, fields, ¶ms) != ERROR_OK) { + struct serdes_wordset wordset = { + .check = (serdes_check_fn_t) freertos_in_word_set, + .value = (serdes_value_fn_t) FreeRTOS_wordset_value, + }; + + if (serdes_read_struct(interp, elements, freertos_params_fields, + &wordset, params) != ERROR_OK) { LOG_ERROR("freertos: unable to read configuration"); goto error; } + list_add(¶ms->list, &freertos_params_list); + result = ERROR_OK; error: return result; diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 113349f..4371830 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -580,16 +580,11 @@ void rtos_free_threadlist(struct rtos *rtos) } } -COMMAND_HANDLER(rtos_list) { - - return ERROR_OK; -} - -static int rtos_conf_add(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { - const struct rtos_type * rtos_conf_add_map[] = { - [ rtos_freertos ] = &FreeRTOS_rtos, - }; +static const struct rtos_type * rtos_conf_map[] = { + [ rtos_freertos ] = &FreeRTOS_rtos, +}; +static rtos_option_t get_rtos_type(Jim_GetOptInfo *goi) { enum rtos_add_options { ADD_OPT_TYPE = 0, }; @@ -599,22 +594,10 @@ static int rtos_conf_add(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { { NULL, -1 }, }; - Jim_GetOptInfo goi; - Jim_Obj *dict; - Jim_Obj **pairs; - int pair_count; Jim_Nvp *nvp; + rtos_option_t result = rtos_invalid; - int result = ERROR_FAIL; - int rtos_type = rtos_invalid; - - if (Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1) != JIM_OK) { - goto error; - } - - Jim_GetOpt_Debug(&goi); - - if (Jim_GetOpt_Nvp(&goi, options, &nvp) != JIM_OK) { + if (Jim_GetOpt_Nvp(goi, options, &nvp) != JIM_OK) { goto error; } @@ -623,7 +606,7 @@ static int rtos_conf_add(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int value_len; struct rtos_lookup_entry *entry; - if (Jim_GetOpt_String(&goi, &value, &value_len) != JIM_OK) { + if (Jim_GetOpt_String(goi, &value, &value_len) != JIM_OK) { goto error; } @@ -634,9 +617,59 @@ static int rtos_conf_add(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { goto error; } - rtos_type = entry->option; + result = entry->option; + } + +error: + return result; +} + +static int rtos_conf_list(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { + Jim_GetOptInfo goi; + + rtos_option_t rtos_type = rtos_invalid; + int result = ERROR_FAIL; + + if (Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1) != JIM_OK) { + goto error; + } + + rtos_type = get_rtos_type(&goi); + + if (rtos_type == rtos_invalid) { + LOG_ERROR("invalid RTOS type provided"); + goto error; } + if (!rtos_conf_map[rtos_type]->conf_list) { + LOG_ERROR("specified RTOS type does not support dynamic configurations"); + goto error; + } + + if (rtos_conf_map[rtos_type]->conf_list() != ERROR_OK) { + goto error; + } + + result = ERROR_OK; +error: + return result; +} + +static int rtos_conf_add(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { + Jim_GetOptInfo goi; + Jim_Obj *dict; + Jim_Obj **pairs; + int pair_count; + + int result = ERROR_FAIL; + int rtos_type = rtos_invalid; + + if (Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1) != JIM_OK) { + goto error; + } + + rtos_type = get_rtos_type(&goi); + if (rtos_type == rtos_invalid) { LOG_ERROR("invalid RTOS type provided"); goto error; @@ -652,12 +685,12 @@ static int rtos_conf_add(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { goto error; } - if (!rtos_conf_add_map[rtos_type]->conf_add) { + if (!rtos_conf_map[rtos_type]->conf_add) { LOG_ERROR("specified RTOS type does not support dynamic configurations"); goto error; } - if (rtos_conf_add_map[rtos_type]->conf_add(interp, pairs, pair_count) != ERROR_OK) { + if (rtos_conf_map[rtos_type]->conf_add(interp, pairs, pair_count) != ERROR_OK) { goto error; } @@ -669,17 +702,17 @@ error: static const struct command_registration rtos_exec_command_handlers[] = { { .name = "list", - .handler = rtos_list, - .mode = COMMAND_EXEC, - .help = "List available RTOS / targets", - .usage = "", + .mode = COMMAND_ANY, + .jim_handler = rtos_conf_list, + .help = "List available RTOS configurations", + .usage = "-type <RTOS type>", }, { .name = "add", .mode = COMMAND_ANY, .jim_handler = rtos_conf_add, .help = "Add RTOS target", - .usage = "-type <RTOS type>", + .usage = "-type <RTOS type> <parameter dictionary>", }, COMMAND_REGISTRATION_DONE }; diff --git a/src/rtos/rtos.h b/src/rtos/rtos.h index 443c10f..e912406 100644 --- a/src/rtos/rtos.h +++ b/src/rtos/rtos.h @@ -71,6 +71,7 @@ struct rtos_type { int (*clean)(struct target *target); char * (*ps_command)(struct target *target); int (*conf_add)(Jim_Interp *, Jim_Obj **, int); + int (*conf_list)(void); }; struct stack_register_offset { diff --git a/src/target/target.c b/src/target/target.c index 729a31b..c449872 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1403,7 +1403,6 @@ int target_register_reset_callback(int (*callback)(struct target *target, entry->priv = priv; list_add(&entry->list, &target_reset_callback_list); - return ERROR_OK; } -- ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ OpenOCD-devel mailing list OpenOCD-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openocd-devel