X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Frtos%2Frtos.c;h=91d9379f30395619c7797a3a178b9341f990532d;hb=88fa831839cf7e45f66064c9c74cfcf59b8d8c7e;hp=1b3a47f9c77c14dc333fc33ecde21450708b00e5;hpb=9ec306e95a07ca9a5a72619618f5ed54e1fc8920;p=fw%2Fopenocd diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 1b3a47f9c..91d9379f3 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -31,25 +31,34 @@ extern struct rtos_type FreeRTOS_rtos; extern struct rtos_type ThreadX_rtos; extern struct rtos_type eCos_rtos; extern struct rtos_type Linux_os; -extern struct rtos_type ChibiOS_rtos; +extern struct rtos_type chibios_rtos; +extern struct rtos_type chromium_ec_rtos; extern struct rtos_type embKernel_rtos; extern struct rtos_type mqx_rtos; extern struct rtos_type uCOS_III_rtos; extern struct rtos_type nuttx_rtos; +extern struct rtos_type hwthread_rtos; +extern struct rtos_type riot_rtos; static struct rtos_type *rtos_types[] = { &ThreadX_rtos, &FreeRTOS_rtos, &eCos_rtos, &Linux_os, - &ChibiOS_rtos, + &chibios_rtos, + &chromium_ec_rtos, &embKernel_rtos, &mqx_rtos, &uCOS_III_rtos, &nuttx_rtos, + &riot_rtos, + /* keep this as last, as it always matches with rtos auto */ + &hwthread_rtos, NULL }; +static int rtos_try_next(struct target *target); + int rtos_thread_packet(struct connection *connection, const char *packet, int packet_size); int rtos_smp_init(struct target *target) @@ -93,9 +102,7 @@ static void os_free(struct target *target) if (!target->rtos) return; - if (target->rtos->symbols) - free(target->rtos->symbols); - + free(target->rtos->symbols); free(target->rtos); target->rtos = NULL; } @@ -117,7 +124,7 @@ int rtos_create(Jim_GetOptInfo *goi, struct target *target) { int x; const char *cp; - struct Jim_Obj *res; + Jim_Obj *res; int e; if (!goi->isconfigure && goi->argc != 0) { @@ -155,6 +162,11 @@ int rtos_create(Jim_GetOptInfo *goi, struct target *target) return JIM_ERR; } +void rtos_destroy(struct target *target) +{ + os_free(target); +} + int gdb_thread_packet(struct connection *connection, char const *packet, int packet_size) { struct target *target = get_target_from_connection(connection); @@ -164,9 +176,9 @@ int gdb_thread_packet(struct connection *connection, char const *packet, int pac return target->rtos->gdb_thread_packet(connection, packet, packet_size); } -static symbol_table_elem_t *next_symbol(struct rtos *os, char *cur_symbol, uint64_t cur_addr) +static struct symbol_table_elem *next_symbol(struct rtos *os, char *cur_symbol, uint64_t cur_addr) { - symbol_table_elem_t *s; + struct symbol_table_elem *s; if (!os->symbols) os->type->get_symbol_list_to_lookup(&os->symbols); @@ -188,7 +200,7 @@ static symbol_table_elem_t *next_symbol(struct rtos *os, char *cur_symbol, uint6 * if 'symbol' is not declared optional */ static bool is_symbol_mandatory(const struct rtos *os, const char *symbol) { - for (symbol_table_elem_t *s = os->symbols; s->symbol_name; ++s) { + for (struct symbol_table_elem *s = os->symbols; s->symbol_name; ++s) { if (!strcmp(s->symbol_name, symbol)) return !s->optional; } @@ -219,8 +231,8 @@ int rtos_qsymbol(struct connection *connection, char const *packet, int packet_s int rtos_detected = 0; uint64_t addr = 0; size_t reply_len; - char reply[GDB_BUFFER_SIZE], cur_sym[GDB_BUFFER_SIZE / 2] = ""; - symbol_table_elem_t *next_sym = NULL; + char reply[GDB_BUFFER_SIZE + 1], cur_sym[GDB_BUFFER_SIZE / 2 + 1] = ""; /* Extra byte for null-termination */ + struct symbol_table_elem *next_sym = NULL; struct target *target = get_target_from_connection(connection); struct rtos *os = target->rtos; @@ -435,6 +447,82 @@ int rtos_thread_packet(struct connection *connection, char const *packet, int pa return GDB_THREAD_PACKET_NOT_CONSUMED; } +static int rtos_put_gdb_reg_list(struct connection *connection, + struct rtos_reg *reg_list, int num_regs) +{ + size_t num_bytes = 1; /* NUL */ + for (int i = 0; i < num_regs; ++i) + num_bytes += DIV_ROUND_UP(reg_list[i].size, 8) * 2; + + char *hex = malloc(num_bytes); + char *hex_p = hex; + + for (int i = 0; i < num_regs; ++i) { + size_t count = DIV_ROUND_UP(reg_list[i].size, 8); + size_t n = hexify(hex_p, reg_list[i].value, count, num_bytes); + hex_p += n; + num_bytes -= n; + } + + gdb_put_packet(connection, hex, strlen(hex)); + free(hex); + + return ERROR_OK; +} + +/** Look through all registers to find this register. */ +int rtos_get_gdb_reg(struct connection *connection, int reg_num) +{ + struct target *target = get_target_from_connection(connection); + int64_t current_threadid = target->rtos->current_threadid; + if ((target->rtos != NULL) && (current_threadid != -1) && + (current_threadid != 0) && + ((current_threadid != target->rtos->current_thread) || + (target->smp))) { /* in smp several current thread are possible */ + struct rtos_reg *reg_list; + int num_regs; + + LOG_DEBUG("getting register %d for thread 0x%" PRIx64 + ", target->rtos->current_thread=0x%" PRIx64, + reg_num, + current_threadid, + target->rtos->current_thread); + + int retval; + if (target->rtos->type->get_thread_reg) { + reg_list = calloc(1, sizeof(*reg_list)); + num_regs = 1; + retval = target->rtos->type->get_thread_reg(target->rtos, + current_threadid, reg_num, ®_list[0]); + if (retval != ERROR_OK) { + LOG_ERROR("RTOS: failed to get register %d", reg_num); + return retval; + } + } else { + retval = target->rtos->type->get_thread_reg_list(target->rtos, + current_threadid, + ®_list, + &num_regs); + if (retval != ERROR_OK) { + LOG_ERROR("RTOS: failed to get register list"); + return retval; + } + } + + for (int i = 0; i < num_regs; ++i) { + if (reg_list[i].number == (uint32_t)reg_num) { + rtos_put_gdb_reg_list(connection, reg_list + i, 1); + free(reg_list); + return ERROR_OK; + } + } + + free(reg_list); + } + return ERROR_FAIL; +} + +/** Return a list of general registers. */ int rtos_get_gdb_reg_list(struct connection *connection) { struct target *target = get_target_from_connection(connection); @@ -443,7 +531,8 @@ int rtos_get_gdb_reg_list(struct connection *connection) (current_threadid != 0) && ((current_threadid != target->rtos->current_thread) || (target->smp))) { /* in smp several current thread are possible */ - char *hex_reg_list; + struct rtos_reg *reg_list; + int num_regs; LOG_DEBUG("RTOS: getting register list for thread 0x%" PRIx64 ", target->rtos->current_thread=0x%" PRIx64 "\r\n", @@ -452,17 +541,31 @@ int rtos_get_gdb_reg_list(struct connection *connection) int retval = target->rtos->type->get_thread_reg_list(target->rtos, current_threadid, - &hex_reg_list); + ®_list, + &num_regs); if (retval != ERROR_OK) { LOG_ERROR("RTOS: failed to get register list"); return retval; } - if (hex_reg_list != NULL) { - gdb_put_packet(connection, hex_reg_list, strlen(hex_reg_list)); - free(hex_reg_list); - return ERROR_OK; - } + rtos_put_gdb_reg_list(connection, reg_list, num_regs); + free(reg_list); + + return ERROR_OK; + } + return ERROR_FAIL; +} + +int rtos_set_reg(struct connection *connection, int reg_num, + uint8_t *reg_value) +{ + struct target *target = get_target_from_connection(connection); + int64_t current_threadid = target->rtos->current_threadid; + if ((target->rtos != NULL) && + (target->rtos->type->set_reg != NULL) && + (current_threadid != -1) && + (current_threadid != 0)) { + return target->rtos->type->set_reg(target->rtos, reg_num, reg_value); } return ERROR_FAIL; } @@ -470,12 +573,9 @@ int rtos_get_gdb_reg_list(struct connection *connection) int rtos_generic_stack_read(struct target *target, const struct rtos_register_stacking *stacking, int64_t stack_ptr, - char **hex_reg_list) + struct rtos_reg **reg_list, + int *num_regs) { - int list_size = 0; - char *tmp_str_ptr; - int64_t new_stack_ptr; - int i; int retval; if (stack_ptr == 0) { @@ -502,10 +602,8 @@ int rtos_generic_stack_read(struct target *target, LOG_OUTPUT("%02X", stack_data[i]); LOG_OUTPUT("\r\n"); #endif - for (i = 0; i < stacking->num_output_registers; i++) - list_size += stacking->register_offsets[i].width_bits/8; - *hex_reg_list = malloc(list_size*2 + 1); - tmp_str_ptr = *hex_reg_list; + + int64_t new_stack_ptr; if (stacking->calculate_process_stack != NULL) { new_stack_ptr = stacking->calculate_process_stack(target, stack_data, stacking, stack_ptr); @@ -513,25 +611,27 @@ int rtos_generic_stack_read(struct target *target, new_stack_ptr = stack_ptr - stacking->stack_growth_direction * stacking->stack_registers_size; } - for (i = 0; i < stacking->num_output_registers; i++) { - int j; - for (j = 0; j < stacking->register_offsets[i].width_bits/8; j++) { - if (stacking->register_offsets[i].offset == -1) - tmp_str_ptr += sprintf(tmp_str_ptr, "%02x", 0); - else if (stacking->register_offsets[i].offset == -2) - tmp_str_ptr += sprintf(tmp_str_ptr, "%02x", - ((uint8_t *)&new_stack_ptr)[j]); - else - tmp_str_ptr += sprintf(tmp_str_ptr, "%02x", - stack_data[stacking->register_offsets[i].offset + j]); - } + + *reg_list = calloc(stacking->num_output_registers, sizeof(struct rtos_reg)); + *num_regs = stacking->num_output_registers; + + for (int i = 0; i < stacking->num_output_registers; ++i) { + (*reg_list)[i].number = stacking->register_offsets[i].number; + (*reg_list)[i].size = stacking->register_offsets[i].width_bits; + + int offset = stacking->register_offsets[i].offset; + if (offset == -2) + buf_cpy(&new_stack_ptr, (*reg_list)[i].value, (*reg_list)[i].size); + else if (offset != -1) + buf_cpy(stack_data + offset, (*reg_list)[i].value, (*reg_list)[i].size); } + free(stack_data); /* LOG_OUTPUT("Output register string: %s\r\n", *hex_reg_list); */ return ERROR_OK; } -int rtos_try_next(struct target *target) +static int rtos_try_next(struct target *target) { struct rtos *os = target->rtos; struct rtos_type **type = rtos_types; @@ -546,10 +646,9 @@ int rtos_try_next(struct target *target) return 0; os->type = *type; - if (os->symbols) { - free(os->symbols); - os->symbols = NULL; - } + + free(os->symbols); + os->symbols = NULL; return 1; }