diff --git a/src/rtos/FreeRTOS.c b/src/rtos/FreeRTOS.c --- a/src/rtos/FreeRTOS.c +++ b/src/rtos/FreeRTOS.c @@ -53,6 +53,22 @@ struct FreeRTOS_params { }; static const struct FreeRTOS_params FreeRTOS_params_list[] = { +#if 1 + { + "riscv", /* 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_RiscV32I_stacking, /* stacking_info */ + NULL, + NULL, + }, +#endif { "cortex_m", /* target_name */ 4, /* thread_count_width; */ @@ -553,3 +569,118 @@ static int FreeRTOS_create(struct target *target) target->rtos->rtos_specific_params = (void *) &FreeRTOS_params_list[i]; return 0; } + +int FreeRTOS_get_thread_reg(struct rtos *rtos, int64_t thread_id, char **hex_reg_list, int index) +{ + int retval, i; + const struct FreeRTOS_params *param= (const struct FreeRTOS_params *) rtos->rtos_specific_params; + int64_t stack_ptr = 0; + struct rtos_register_stacking *stack; + *hex_reg_list = NULL; + if (rtos == NULL) + return -1; + + if (thread_id == 0) + return -2; + + if (rtos->rtos_specific_params == NULL) + return -1; + + + /* Read the stack pointer */ + retval = target_read_buffer(rtos->target, + thread_id + param->thread_stack_offset, + param->pointer_width, + (uint8_t *)&stack_ptr); + if (retval != ERROR_OK) { + LOG_ERROR("Error reading stack frame from FreeRTOS thread"); + return retval; + } + LOG_DEBUG("FreeRTOS: Read stack pointer at 0x%" PRIx64 ", value 0x%" PRIx64 "\r\n", + thread_id + param->thread_stack_offset, + stack_ptr); + + /* Check for armv7m with *enabled* FPU, i.e. a Cortex-M4F */ + int cm4_fpu_enabled = 0; + struct armv7m_common *armv7m_target = target_to_armv7m(rtos->target); + if (is_armv7m(armv7m_target)) { + if (armv7m_target->fp_feature == FPv4_SP) { + /* Found ARM v7m target which includes a FPU */ + uint32_t cpacr; + + retval = target_read_u32(rtos->target, FPU_CPACR, &cpacr); + if (retval != ERROR_OK) { + LOG_ERROR("Could not read CPACR register to check FPU state"); + return -1; + } + + /* Check if CP10 and CP11 are set to full access. */ + if (cpacr & 0x00F00000) { + /* Found target with enabled FPU */ + cm4_fpu_enabled = 1; + } + } + } + + if (cm4_fpu_enabled == 1) { + /* Read the LR to decide between stacking with or without FPU */ + uint32_t LR_svc = 0; + retval = target_read_buffer(rtos->target, + stack_ptr + 0x20, + param->pointer_width, + (uint8_t *)&LR_svc); + if (retval != ERROR_OK) { + LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n"); + return retval; + } + if ((LR_svc & 0x10) == 0) + { + stack = (struct rtos_register_stacking*)param->stacking_info_cm4f_fpu; + } + else + { + stack = (struct rtos_register_stacking*)param->stacking_info_cm4f; + } + } + else + { + stack = (struct rtos_register_stacking*)param->stacking_info_cm3; + } + + /* Read the stack */ + uint8_t *stack_data = malloc(stack->stack_registers_size); + uint32_t address = stack_ptr; + + if (stack->stack_growth_direction == 1) + address -= stack->stack_registers_size; + retval = target_read_buffer(rtos->target, address, stack->stack_registers_size, stack_data); + if (retval != ERROR_OK) { + free(stack_data); + LOG_ERROR("Error reading stack frame from thread"); + return retval; + } + + /* Remap */ + if(index >= stack->num_output_registers) + { + if(index == 0x20) + { + index = 0x1; + } + } + + if(NULL==(*hex_reg_list = malloc(stack->register_offsets[index].width_bits/4 + 1))) + return ERROR_FAIL; + + memset(*hex_reg_list, 0x0, stack->register_offsets[index].width_bits/4 + 1); + char *tmp_str_ptr = *hex_reg_list; + + for (i= 0; i < stack->register_offsets[index].width_bits/8; i++) + { + tmp_str_ptr += sprintf(tmp_str_ptr, "%02x", + stack_data[stack->register_offsets[index].offset + i]); + } + + free(stack_data); + return ERROR_OK; +} \ No newline at end of file diff --git a/src/rtos/ThreadX.c b/src/rtos/ThreadX.c --- a/src/rtos/ThreadX.c +++ b/src/rtos/ThreadX.c @@ -141,6 +141,20 @@ struct ThreadX_params { }; static const struct ThreadX_params ThreadX_params_list[] = { +#if 0 + { + "riscv", /* target_name */ + 4, /* pointer_width; */ + 8, /* thread_stack_offset; */ + 40, /* thread_name_offset; */ + 48, /* thread_state_offset; */ + 136, /* thread_next_offset */ + &rtos_standard_RiscV32I_stacking, /* stacking_info */ + 1, /* stacking_info_nb */ + NULL, /* fn_get_stacking_info */ + NULL, /* fn_is_thread_id_valid */ + }, +#endif { "cortex_m", /* target_name */ 4, /* pointer_width; */ new mode 100755 diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -436,6 +436,8 @@ int rtos_get_gdb_reg_list(struct connection *connection) return ERROR_FAIL; } + + int rtos_generic_stack_read(struct target *target, const struct rtos_register_stacking *stacking, int64_t stack_ptr, @@ -500,6 +502,35 @@ int rtos_generic_stack_read(struct target *target, return ERROR_OK; } +int rtos_get_gdb_reg(struct connection *connection, int index) +{ + 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 */ + char *hex_reg_list = NULL; + + + if(0 == strcmp(target->rtos->type->name, FreeRTOS_rtos.name) ) + { + int FreeRTOS_get_thread_reg(struct rtos *rtos, int64_t thread_id, char **hex_reg_list, int index); + if(ERROR_OK!=FreeRTOS_get_thread_reg(target->rtos, current_threadid, &hex_reg_list, index)) + { + return ERROR_FAIL; + } + } + + if (hex_reg_list != NULL) { + gdb_put_packet(connection, hex_reg_list, strlen(hex_reg_list)); + free(hex_reg_list); + return ERROR_OK; + } + } + return ERROR_FAIL; +} + int rtos_try_next(struct target *target) { struct rtos *os = target->rtos; diff --git a/src/rtos/rtos.h b/src/rtos/rtos.h --- a/src/rtos/rtos.h +++ b/src/rtos/rtos.h @@ -107,5 +107,5 @@ void rtos_free_threadlist(struct rtos *rtos); int rtos_smp_init(struct target *target); /* function for handling symbol access */ int rtos_qsymbol(struct connection *connection, char const *packet, int packet_size); - +int rtos_get_gdb_reg(struct connection *connection, int index); #endif /* OPENOCD_RTOS_RTOS_H */ diff --git a/src/rtos/rtos_standard_stackings.c b/src/rtos/rtos_standard_stackings.c --- a/src/rtos/rtos_standard_stackings.c +++ b/src/rtos/rtos_standard_stackings.c @@ -23,6 +23,43 @@ #include "rtos.h" #include "target/armv7m.h" +#include "log.h" + +static const struct stack_register_offset rtos_standard_RiscV32I_stack_offsets[] = { + { -1 , 32 }, /* X0 */ + { 0x00, 32 }, /* x1 ra */ + { 0x04, 32 }, /* x2 sp */ + { 0x08, 32 }, /* x3 gp */ + { 0x0c, 32 }, /* x4 tp */ + { 0x10, 32 }, /* x5 t0 */ + { 0x14, 32 }, /* x6 t1 */ + { 0x18, 32 }, /* x7 t2 */ + { 0x1c, 32 }, /* x8 s0/fp */ + { 0x20, 32 }, /* x9 s1 */ + { 0x24, 32 }, /* x10 a0 */ + { 0x28, 32 }, /* x11 a1 */ + { 0x2c, 32 }, /* x12 a2 */ + { 0x30, 32 }, /* x13 a3 */ + { 0x34, 32 }, /* x14 a4 */ + { 0x38, 32 }, /* x15 a5 */ + { 0x3c, 32 }, /* x16 a6 */ + { 0x40, 32 }, /* x17 a7 */ + { 0x44, 32 }, /* x18 s2 */ + { 0x48, 32 }, /* x19 s3 */ + { 0x4c, 32 }, /* x20 s4 */ + { 0x50, 32 }, /* x21 s5 */ + { 0x54, 32 }, /* x22 s6 */ + { 0x58, 32 }, /* x23 s7 */ + { 0x5c, 32 }, /* x24 s8 */ + { 0x60, 32 }, /* x25 s9 */ + { 0x64, 32 }, /* x26 s10 */ + { 0x68, 32 }, /* x27 s11 */ + { 0x6c, 32 }, /* x28 t3 */ + { 0x70, 32 }, /* x29 t4 */ + { 0x74, 32 }, /* x30 t5 */ + { 0x78, 32 }, /* x31 t6 */ + { 0x80, 32 } /* PC */ +}; static const struct stack_register_offset rtos_standard_Cortex_M3_stack_offsets[ARMV7M_NUM_CORE_REGS] = { { 0x20, 32 }, /* r0 */ { 0x24, 32 }, /* r1 */ @@ -225,10 +262,54 @@ static int64_t rtos_standard_Cortex_M3_stack_align(struct target *target, int64_t stack_ptr) { const int XPSR_OFFSET = 0x3c; +#if 0 + int i, *ptr=(int*)stack_data; + for(i=0; i<17; i++) + { + LOG_INFO("X%02d = 0x%08x.", i, *ptr++); + } +#endif return rtos_Cortex_M_stack_align(target, stack_data, stacking, stack_ptr, XPSR_OFFSET); } +int64_t rtos_standard_RiscV32I_stack_align(struct target *target, + const uint8_t *stack_data, const struct rtos_register_stacking *stacking, + int64_t stack_ptr) +{ + int64_t new_stack_ptr; + int64_t aligned_stack_ptr; +#if 0 + int i, *ptr=(int*)stack_data; + for(i=1; i<32; i++) + { + LOG_INFO("X%02d = 0x%08x.", i, *ptr++); + } +#endif + new_stack_ptr = stack_ptr - stacking->stack_growth_direction * + stacking->stack_registers_size; + + aligned_stack_ptr = new_stack_ptr & ~((int64_t)4 - 1); + if (aligned_stack_ptr != new_stack_ptr && + stacking->stack_growth_direction == -1) { + /* If we have a downward growing stack, the simple alignment code + * above results in a wrong result (since it rounds down to nearest + * alignment). We want to round up so add an extra align. + */ + aligned_stack_ptr += (int64_t)4; + } + //LOG_INFO("raw 0x%lx,before 0x%lx, now 0x%lx.", stack_ptr, new_stack_ptr, aligned_stack_ptr); + return aligned_stack_ptr; +} + +const struct rtos_register_stacking rtos_standard_RiscV32I_stacking = { + 0x84, /* stack_registers_size */ + -1, /* stack_growth_direction */ + 32, /* num_output_registers */ + rtos_standard_RiscV32I_stack_align, /* stack_alignment */ + rtos_standard_RiscV32I_stack_offsets /* register_offsets */ +}; + const struct rtos_register_stacking rtos_standard_Cortex_M3_stacking = { 0x40, /* stack_registers_size */ -1, /* stack_growth_direction */ diff --git a/src/rtos/rtos_standard_stackings.h b/src/rtos/rtos_standard_stackings.h --- a/src/rtos/rtos_standard_stackings.h +++ b/src/rtos/rtos_standard_stackings.h @@ -24,7 +24,7 @@ #endif #include "rtos.h" - +extern const struct rtos_register_stacking rtos_standard_RiscV32I_stacking; extern const struct rtos_register_stacking rtos_standard_Cortex_M3_stacking; extern const struct rtos_register_stacking rtos_standard_Cortex_M4F_stacking; extern const struct rtos_register_stacking rtos_standard_Cortex_M4F_FPU_stacking; diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -255,7 +255,7 @@ static int gdb_get_char_inner(struct connection *connection, int *next_char) #ifdef _DEBUG_GDB_IO_ debug_buffer = strndup(gdb_con->buffer, gdb_con->buf_cnt); - LOG_DEBUG("received '%s'", debug_buffer); + LOG_INFO("received '%s'", debug_buffer); free(debug_buffer); #endif @@ -267,7 +267,7 @@ static int gdb_get_char_inner(struct connection *connection, int *next_char) else connection->input_pending = 0; #ifdef _DEBUG_GDB_IO_ - LOG_DEBUG("returned char '%c' (0x%2.2x)", *next_char, *next_char); + LOG_INFO("returned char '%c' (0x%2.2x)", *next_char, *next_char); #endif return retval; @@ -293,7 +293,7 @@ static inline int gdb_get_char_fast(struct connection *connection, connection->input_pending = 0; #ifdef _DEBUG_GDB_IO_ - LOG_DEBUG("returned char '%c' (0x%2.2x)", *next_char, *next_char); + LOG_INFO("returned char '%c' (0x%2.2x)", *next_char, *next_char); #endif return ERROR_OK; @@ -377,7 +377,7 @@ static int gdb_put_packet_inner(struct connection *connection, if (reply == '$') { /* fix a problem with some IAR tools */ gdb_putback_char(connection, reply); - LOG_DEBUG("Unexpected start of new packet"); + LOG_INFO("Unexpected start of new packet"); break; } @@ -388,7 +388,7 @@ static int gdb_put_packet_inner(struct connection *connection, while (1) { #ifdef _DEBUG_GDB_IO_ debug_buffer = strndup(buffer, len); - LOG_DEBUG("sending packet '$%s#%2.2x'", debug_buffer, my_checksum); + LOG_INFO("sending packet '$%s#%2.2x'", debug_buffer, my_checksum); free(debug_buffer); #endif @@ -608,7 +608,7 @@ static int gdb_get_packet_inner(struct connection *connection, return retval; #ifdef _DEBUG_GDB_IO_ - LOG_DEBUG("character: '%c'", character); + LOG_INFO("character: '%c'", character); #endif switch (character) { @@ -1140,7 +1140,7 @@ static int gdb_get_registers_packet(struct connection *connection, int i; #ifdef _DEBUG_GDB_IO_ - LOG_DEBUG("-"); + LOG_INFO("-"); #endif if ((target->rtos != NULL) && (ERROR_OK == rtos_get_gdb_reg_list(connection))) @@ -1180,7 +1180,7 @@ static int gdb_get_registers_packet(struct connection *connection, { char *reg_packet_p_debug; reg_packet_p_debug = strndup(reg_packet, reg_packet_size); - LOG_DEBUG("reg_packet: %s", reg_packet_p_debug); + LOG_INFO("reg_packet: %s", reg_packet_p_debug); free(reg_packet_p_debug); } #endif @@ -1204,7 +1204,7 @@ static int gdb_set_registers_packet(struct connection *connection, char const *packet_p; #ifdef _DEBUG_GDB_IO_ - LOG_DEBUG("-"); + LOG_INFO("-"); #endif /* skip command character */ @@ -1265,9 +1265,11 @@ static int gdb_get_register_packet(struct connection *connection, int retval; #ifdef _DEBUG_GDB_IO_ - LOG_DEBUG("-"); + LOG_INFO("-"); #endif - + if ((target->rtos != NULL) && (ERROR_OK == rtos_get_gdb_reg(connection, reg_num))) + return ERROR_OK; + retval = target_get_gdb_reg_list(target, ®_list, ®_list_size, REG_CLASS_ALL); if (retval != ERROR_OK)