diff --git a/doc/openocd.texi b/doc/openocd.texi index 3f229704c..0e4c5f6e9 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2227,7 +2227,7 @@ the port @var{number} defaults to 6666. When specified as "disabled", this service is not activated. @end deffn -@deffn {Config Command} {telnet_port} [number] +@deffn {Config Command} {telnet port} [number] Specify or query the port on which to listen for incoming telnet connections. This port is intended for interaction with one human through TCL commands. diff --git a/src/flash/nor/atsame5.c b/src/flash/nor/atsame5.c index c590081fc..a6ac9060a 100644 --- a/src/flash/nor/atsame5.c +++ b/src/flash/nor/atsame5.c @@ -85,6 +85,9 @@ #define SAME_SERIES_51 0x01 #define SAME_SERIES_53 0x03 #define SAME_SERIES_54 0x04 +#define PIC32CXSG_SERIES_41 0x07 +#define PIC32CXSG_SERIES_60 0x00 +#define PIC32CXSG_SERIES_61 0x02 /* Device ID macros */ #define SAMD_GET_PROCESSOR(id) (id >> 28) @@ -148,6 +151,27 @@ static const struct samd_part same54_parts[] = { { 0x03, "SAME54N19A", 512, 192 }, }; +/* See PIC32CX SG41/SG60/SG61 Family Silicon Errata and Datasheet Clarifications + * DS80000985G */ +/* Known PIC32CX-SG41 parts. */ +static const struct samd_part pic32cxsg41_parts[] = { + { 0x00, "PIC32CX1025SG41128", 1024, 256 }, + { 0x01, "PIC32CX1025SG41100", 1024, 256 }, + { 0x02, "PIC32CX1025SG41064", 1024, 256 }, +}; + +/* Known PIC32CX-SG60 parts. */ +static const struct samd_part pic32cxsg60_parts[] = { + { 0x00, "PIC32CX1025SG60128", 1024, 256 }, + { 0x01, "PIC32CX1025SG60100", 1024, 256 }, +}; + +/* Known PIC32CX-SG61 parts. */ +static const struct samd_part pic32cxsg61_parts[] = { + { 0x00, "PIC32CX1025SG61128", 1024, 256 }, + { 0x01, "PIC32CX1025SG61100", 1024, 256 }, +}; + /* Each family of parts contains a parts table in the DEVSEL field of DID. The * processor ID, family ID, and series ID are used to determine which exact * family this is and then we can use the corresponding table. */ @@ -169,6 +193,12 @@ static const struct samd_family samd_families[] = { same53_parts, ARRAY_SIZE(same53_parts) }, { SAMD_PROCESSOR_M4, SAMD_FAMILY_E, SAME_SERIES_54, same54_parts, ARRAY_SIZE(same54_parts) }, + { SAMD_PROCESSOR_M4, SAMD_FAMILY_E, PIC32CXSG_SERIES_41, + pic32cxsg41_parts, ARRAY_SIZE(pic32cxsg41_parts) }, + { SAMD_PROCESSOR_M4, SAMD_FAMILY_E, PIC32CXSG_SERIES_60, + pic32cxsg60_parts, ARRAY_SIZE(pic32cxsg60_parts) }, + { SAMD_PROCESSOR_M4, SAMD_FAMILY_E, PIC32CXSG_SERIES_61, + pic32cxsg61_parts, ARRAY_SIZE(pic32cxsg61_parts) }, }; struct samd_info { diff --git a/src/helper/binarybuffer.c b/src/helper/binarybuffer.c index c25383dc6..a7ca5af9d 100644 --- a/src/helper/binarybuffer.c +++ b/src/helper/binarybuffer.c @@ -57,49 +57,49 @@ void *buf_cpy(const void *from, void *_to, unsigned size) return _to; } -static bool buf_cmp_masked(uint8_t a, uint8_t b, uint8_t m) +static bool buf_eq_masked(uint8_t a, uint8_t b, uint8_t m) { - return (a & m) != (b & m); + return (a & m) == (b & m); } -static bool buf_cmp_trailing(uint8_t a, uint8_t b, uint8_t m, unsigned trailing) +static bool buf_eq_trailing(uint8_t a, uint8_t b, uint8_t m, unsigned trailing) { uint8_t mask = (1 << trailing) - 1; - return buf_cmp_masked(a, b, mask & m); + return buf_eq_masked(a, b, mask & m); } -bool buf_cmp(const void *_buf1, const void *_buf2, unsigned size) +bool buf_eq(const void *_buf1, const void *_buf2, unsigned size) { if (!_buf1 || !_buf2) - return _buf1 != _buf2; + return _buf1 == _buf2; unsigned last = size / 8; if (memcmp(_buf1, _buf2, last) != 0) - return true; + return false; unsigned trailing = size % 8; if (!trailing) - return false; + return true; const uint8_t *buf1 = _buf1, *buf2 = _buf2; - return buf_cmp_trailing(buf1[last], buf2[last], 0xff, trailing); + return buf_eq_trailing(buf1[last], buf2[last], 0xff, trailing); } -bool buf_cmp_mask(const void *_buf1, const void *_buf2, +bool buf_eq_mask(const void *_buf1, const void *_buf2, const void *_mask, unsigned size) { if (!_buf1 || !_buf2) - return _buf1 != _buf2 || _buf1 != _mask; + return _buf1 == _buf2 && _buf1 == _mask; const uint8_t *buf1 = _buf1, *buf2 = _buf2, *mask = _mask; unsigned last = size / 8; for (unsigned i = 0; i < last; i++) { - if (buf_cmp_masked(buf1[i], buf2[i], mask[i])) - return true; + if (!buf_eq_masked(buf1[i], buf2[i], mask[i])) + return false; } unsigned trailing = size % 8; if (!trailing) - return false; - return buf_cmp_trailing(buf1[last], buf2[last], mask[last], trailing); + return true; + return buf_eq_trailing(buf1[last], buf2[last], mask[last], trailing); } void *buf_set_ones(void *_buf, unsigned size) diff --git a/src/helper/binarybuffer.h b/src/helper/binarybuffer.h index df4199837..ed13b980f 100644 --- a/src/helper/binarybuffer.h +++ b/src/helper/binarybuffer.h @@ -172,8 +172,8 @@ static inline uint64_t buf_get_u64(const uint8_t *_buffer, */ uint32_t flip_u32(uint32_t value, unsigned width); -bool buf_cmp(const void *buf1, const void *buf2, unsigned size); -bool buf_cmp_mask(const void *buf1, const void *buf2, +bool buf_eq(const void *buf1, const void *buf2, unsigned size); +bool buf_eq_mask(const void *buf1, const void *buf2, const void *mask, unsigned size); /** diff --git a/src/jtag/core.c b/src/jtag/core.c index 9eae5e74b..a6f38a19d 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -881,9 +881,9 @@ static int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value, int compare_failed; if (in_check_mask) - compare_failed = buf_cmp_mask(captured, in_check_value, in_check_mask, num_bits); + compare_failed = !buf_eq_mask(captured, in_check_value, in_check_mask, num_bits); else - compare_failed = buf_cmp(captured, in_check_value, num_bits); + compare_failed = !buf_eq(captured, in_check_value, num_bits); if (compare_failed) { char *captured_str, *in_check_value_str; diff --git a/src/rtos/nuttx.c b/src/rtos/nuttx.c index 910014889..821e55088 100644 --- a/src/rtos/nuttx.c +++ b/src/rtos/nuttx.c @@ -32,7 +32,6 @@ struct nuttx_params { const char *target_name; const struct rtos_register_stacking *stacking; - const struct rtos_register_stacking *(*select_stackinfo)(struct target *target); }; /* @@ -56,19 +55,12 @@ struct symbols { bool optional; }; -/* Used to index the list of retrieved symbols. See nuttx_symbol_list for the order. */ -enum nuttx_symbol_vals { - NX_SYM_READYTORUN = 0, - NX_SYM_PIDHASH, - NX_SYM_NPIDHASH, - NX_SYM_TCB_INFO, -}; - static const struct symbols nuttx_symbol_list[] = { { "g_readytorun", false }, { "g_pidhash", false }, { "g_npidhash", false }, { "g_tcbinfo", false }, + { "g_reg_offs", false}, { NULL, false } }; @@ -86,18 +78,14 @@ static char *task_state_str[] = { "STOPPED", }; -static const struct rtos_register_stacking *cortexm_select_stackinfo(struct target *target); - static const struct nuttx_params nuttx_params_list[] = { { .target_name = "cortex_m", - .stacking = NULL, - .select_stackinfo = cortexm_select_stackinfo, + .stacking = &nuttx_stacking_cortex_m, }, { .target_name = "hla_target", - .stacking = NULL, - .select_stackinfo = cortexm_select_stackinfo, + .stacking = &nuttx_stacking_cortex_m, }, { .target_name = "esp32", @@ -117,28 +105,6 @@ static const struct nuttx_params nuttx_params_list[] = { }, }; -static bool cortexm_hasfpu(struct target *target) -{ - uint32_t cpacr; - struct armv7m_common *armv7m_target = target_to_armv7m(target); - - if (!is_armv7m(armv7m_target) || armv7m_target->fp_feature == FP_NONE) - return false; - - int retval = target_read_u32(target, FPU_CPACR, &cpacr); - if (retval != ERROR_OK) { - LOG_ERROR("Could not read CPACR register to check FPU state"); - return false; - } - - return cpacr & 0x00F00000; -} - -static const struct rtos_register_stacking *cortexm_select_stackinfo(struct target *target) -{ - return cortexm_hasfpu(target) ? &nuttx_stacking_cortex_m_fpu : &nuttx_stacking_cortex_m; -} - static bool nuttx_detect_rtos(struct target *target) { if (target->rtos->symbols && @@ -371,29 +337,25 @@ static int nuttx_getreg_current_thread(struct rtos *rtos, static int nuttx_getregs_fromstack(struct rtos *rtos, int64_t thread_id, struct rtos_reg **reg_list, int *num_regs) { - uint16_t xcpreg_off; + uint16_t regs_off; uint32_t regsaddr; const struct nuttx_params *priv = rtos->rtos_specific_params; const struct rtos_register_stacking *stacking = priv->stacking; if (!stacking) { - if (priv->select_stackinfo) { - stacking = priv->select_stackinfo(rtos->target); - } else { - LOG_ERROR("Can't find a way to get stacking info"); - return ERROR_FAIL; - } + LOG_ERROR("Can't find a way to get stacking info"); + return ERROR_FAIL; } int ret = target_read_u16(rtos->target, rtos->symbols[NX_SYM_TCB_INFO].address + offsetof(struct tcbinfo, regs_off), - &xcpreg_off); + ®s_off); if (ret != ERROR_OK) { LOG_ERROR("Failed to read registers' offset: ret = %d", ret); return ERROR_FAIL; } - ret = target_read_u32(rtos->target, thread_id + xcpreg_off, ®saddr); + ret = target_read_u32(rtos->target, thread_id + regs_off, ®saddr); if (ret != ERROR_OK) { LOG_ERROR("Failed to read registers' address: ret = %d", ret); return ERROR_FAIL; diff --git a/src/rtos/rtos_nuttx_stackings.c b/src/rtos/rtos_nuttx_stackings.c index b70cccb33..6faa56a66 100644 --- a/src/rtos/rtos_nuttx_stackings.c +++ b/src/rtos/rtos_nuttx_stackings.c @@ -9,62 +9,102 @@ #include "rtos_nuttx_stackings.h" #include "rtos_standard_stackings.h" #include +#include -/* see arch/arm/include/armv7-m/irq_cmnvector.h */ +/* The cortex_m target uses nuttx_tcbinfo_stack_read which uses a symbol + * provided by Nuttx to read the registers from memory and place them directly + * in the order we need. This is because the register offsets change with + * different versions of Nuttx, FPU vs non-FPU and ARMv7 vs ARMv8. + * This allows a single function to work with many versions. + */ static const struct stack_register_offset nuttx_stack_offsets_cortex_m[] = { - { ARMV7M_R0, 0x28, 32 }, /* r0 */ - { ARMV7M_R1, 0x2c, 32 }, /* r1 */ - { ARMV7M_R2, 0x30, 32 }, /* r2 */ - { ARMV7M_R3, 0x34, 32 }, /* r3 */ - { ARMV7M_R4, 0x08, 32 }, /* r4 */ - { ARMV7M_R5, 0x0c, 32 }, /* r5 */ - { ARMV7M_R6, 0x10, 32 }, /* r6 */ - { ARMV7M_R7, 0x14, 32 }, /* r7 */ - { ARMV7M_R8, 0x18, 32 }, /* r8 */ - { ARMV7M_R9, 0x1c, 32 }, /* r9 */ - { ARMV7M_R10, 0x20, 32 }, /* r10 */ - { ARMV7M_R11, 0x24, 32 }, /* r11 */ - { ARMV7M_R12, 0x38, 32 }, /* r12 */ - { ARMV7M_R13, 0, 32 }, /* sp */ - { ARMV7M_R14, 0x3c, 32 }, /* lr */ - { ARMV7M_PC, 0x40, 32 }, /* pc */ - { ARMV7M_XPSR, 0x44, 32 }, /* xPSR */ + { ARMV7M_R0, 0, 32 }, /* r0 */ + { ARMV7M_R1, 4, 32 }, /* r1 */ + { ARMV7M_R2, 8, 32 }, /* r2 */ + { ARMV7M_R3, 12, 32 }, /* r3 */ + { ARMV7M_R4, 16, 32 }, /* r4 */ + { ARMV7M_R5, 20, 32 }, /* r5 */ + { ARMV7M_R6, 24, 32 }, /* r6 */ + { ARMV7M_R7, 28, 32 }, /* r7 */ + { ARMV7M_R8, 32, 32 }, /* r8 */ + { ARMV7M_R9, 36, 32 }, /* r9 */ + { ARMV7M_R10, 40, 32 }, /* r10 */ + { ARMV7M_R11, 44, 32 }, /* r11 */ + { ARMV7M_R12, 48, 32 }, /* r12 */ + { ARMV7M_R13, 52, 32 }, /* sp */ + { ARMV7M_R14, 56, 32 }, /* lr */ + { ARMV7M_PC, 60, 32 }, /* pc */ + { ARMV7M_XPSR, 64, 32 }, /* xPSR */ }; +/* The Nuttx stack frame for most architectures has some registers placed + * by hardware and some by software. The hardware register order and number does not change + * but the software registers may change with different versions of Nuttx. + * For example with ARMv7, nuttx-12.3.0 added a new register which changed all + * the offsets. We can either create separate offset tables for each version of Nuttx + * which will break again in the future, or read the offsets from the TCB info. + * Nuttx provides a symbol (g_reg_offs) which holds all the offsets for each stored register. + * This offset table is stored in GDB org.gnu.gdb.xxx feature order. + * The same order we need. + * Please refer: + * https://sourceware.org/gdb/current/onlinedocs/gdb/ARM-Features.html + * https://sourceware.org/gdb/current/onlinedocs/gdb/RISC_002dV-Features.html + */ +static int nuttx_cortex_m_tcbinfo_stack_read(struct target *target, + int64_t stack_ptr, const struct rtos_register_stacking *stacking, + uint8_t *stack_data) +{ + struct rtos *rtos = target->rtos; + target_addr_t xcpreg_off = rtos->symbols[NX_SYM_REG_OFFSETS].address; + + for (int i = 0; i < stacking->num_output_registers; ++i) { + uint16_t stack_reg_offset; + int ret = target_read_u16(rtos->target, xcpreg_off + 2 * i, &stack_reg_offset); + if (ret != ERROR_OK) { + LOG_ERROR("Failed to read stack_reg_offset: ret = %d", ret); + return ret; + } + if (stack_reg_offset != UINT16_MAX && stacking->register_offsets[i].offset >= 0) { + ret = target_read_buffer(target, + stack_ptr + stack_reg_offset, + stacking->register_offsets[i].width_bits / 8, + &stack_data[stacking->register_offsets[i].offset]); + if (ret != ERROR_OK) { + LOG_ERROR("Failed to read register: ret = %d", ret); + return ret; + } + } + } + + /* Offset match nuttx_stack_offsets_cortex_m */ + const int XPSR_OFFSET = 64; + const int SP_OFFSET = 52; + /* Nuttx stack frames (produced in exception_common) store the SP of the ISR minus + * the hardware stack frame size. This SP may include an additional 4 byte alignment + * depending in xPSR[9]. The Nuttx stack frame stores post alignment since the + * hardware will add/remove automatically on both enter/exit. + * We need to adjust the SP to get the real SP of the stack. + * See Arm Reference manual "Stack alignment on exception entry" + */ + uint32_t xpsr = target_buffer_get_u32(target, &stack_data[XPSR_OFFSET]); + if (xpsr & BIT(9)) { + uint32_t sp = target_buffer_get_u32(target, &stack_data[SP_OFFSET]); + target_buffer_set_u32(target, &stack_data[SP_OFFSET], sp - 4 * stacking->stack_growth_direction); + } + + return ERROR_OK; +} + const struct rtos_register_stacking nuttx_stacking_cortex_m = { - .stack_registers_size = 0x48, + /* nuttx_tcbinfo_stack_read transforms the stack into just output registers */ + .stack_registers_size = ARRAY_SIZE(nuttx_stack_offsets_cortex_m) * 4, .stack_growth_direction = -1, - .num_output_registers = 17, + .num_output_registers = ARRAY_SIZE(nuttx_stack_offsets_cortex_m), + .read_stack = nuttx_cortex_m_tcbinfo_stack_read, + .calculate_process_stack = NULL, /* Stack alignment done in nuttx_cortex_m_tcbinfo_stack_read */ .register_offsets = nuttx_stack_offsets_cortex_m, }; -static const struct stack_register_offset nuttx_stack_offsets_cortex_m_fpu[] = { - { ARMV7M_R0, 0x6c, 32 }, /* r0 */ - { ARMV7M_R1, 0x70, 32 }, /* r1 */ - { ARMV7M_R2, 0x74, 32 }, /* r2 */ - { ARMV7M_R3, 0x78, 32 }, /* r3 */ - { ARMV7M_R4, 0x08, 32 }, /* r4 */ - { ARMV7M_R5, 0x0c, 32 }, /* r5 */ - { ARMV7M_R6, 0x10, 32 }, /* r6 */ - { ARMV7M_R7, 0x14, 32 }, /* r7 */ - { ARMV7M_R8, 0x18, 32 }, /* r8 */ - { ARMV7M_R9, 0x1c, 32 }, /* r9 */ - { ARMV7M_R10, 0x20, 32 }, /* r10 */ - { ARMV7M_R11, 0x24, 32 }, /* r11 */ - { ARMV7M_R12, 0x7c, 32 }, /* r12 */ - { ARMV7M_R13, 0, 32 }, /* sp */ - { ARMV7M_R14, 0x80, 32 }, /* lr */ - { ARMV7M_PC, 0x84, 32 }, /* pc */ - { ARMV7M_XPSR, 0x88, 32 }, /* xPSR */ -}; - -const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu = { - .stack_registers_size = 0x8c, - .stack_growth_direction = -1, - .num_output_registers = 17, - .register_offsets = nuttx_stack_offsets_cortex_m_fpu, -}; - static const struct stack_register_offset nuttx_stack_offsets_riscv[] = { { GDB_REGNO_ZERO, -1, 32 }, { GDB_REGNO_RA, 0x04, 32 }, diff --git a/src/rtos/rtos_nuttx_stackings.h b/src/rtos/rtos_nuttx_stackings.h index 213a06033..5d55e7545 100644 --- a/src/rtos/rtos_nuttx_stackings.h +++ b/src/rtos/rtos_nuttx_stackings.h @@ -5,6 +5,15 @@ #include "rtos.h" +/* Used to index the list of retrieved symbols. See nuttx_symbol_list for the order. */ +enum nuttx_symbol_vals { + NX_SYM_READYTORUN = 0, + NX_SYM_PIDHASH, + NX_SYM_NPIDHASH, + NX_SYM_TCB_INFO, + NX_SYM_REG_OFFSETS, +}; + extern const struct rtos_register_stacking nuttx_stacking_cortex_m; extern const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu; extern const struct rtos_register_stacking nuttx_riscv_stacking; diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 6c4931b07..85531377d 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1838,18 +1838,9 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection, return ERROR_FAIL; } retval = breakpoint_add(target, address, size, bp_type); - if (retval == ERROR_NOT_IMPLEMENTED) { - /* Send empty reply to report that breakpoints of this type are not supported */ - gdb_put_packet(connection, "", 0); - } else if (retval != ERROR_OK) { - retval = gdb_error(connection, retval); - if (retval != ERROR_OK) - return retval; - } else - gdb_put_packet(connection, "OK", 2); } else { - breakpoint_remove(target, address); - gdb_put_packet(connection, "OK", 2); + assert(packet[0] == 'z'); + retval = breakpoint_remove(target, address); } break; case 2: @@ -1858,26 +1849,26 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection, { if (packet[0] == 'Z') { retval = watchpoint_add(target, address, size, wp_type, 0, WATCHPOINT_IGNORE_DATA_VALUE_MASK); - if (retval == ERROR_NOT_IMPLEMENTED) { - /* Send empty reply to report that watchpoints of this type are not supported */ - gdb_put_packet(connection, "", 0); - } else if (retval != ERROR_OK) { - retval = gdb_error(connection, retval); - if (retval != ERROR_OK) - return retval; - } else - gdb_put_packet(connection, "OK", 2); } else { - watchpoint_remove(target, address); - gdb_put_packet(connection, "OK", 2); + assert(packet[0] == 'z'); + retval = watchpoint_remove(target, address); } break; } default: + { + retval = ERROR_NOT_IMPLEMENTED; break; + } } - return ERROR_OK; + if (retval == ERROR_NOT_IMPLEMENTED) { + /* Send empty reply to report that watchpoints of this type are not supported */ + return gdb_put_packet(connection, "", 0); + } + if (retval != ERROR_OK) + return gdb_error(connection, retval); + return gdb_put_packet(connection, "OK", 2); } /* print out a string and allocate more space as needed, diff --git a/src/server/startup.tcl b/src/server/startup.tcl index ebfb0562e..cf3eca36e 100644 --- a/src/server/startup.tcl +++ b/src/server/startup.tcl @@ -113,3 +113,9 @@ proc "tcl_trace" {state} { echo "DEPRECATED! use 'tcl trace' not 'tcl_trace'" eval tcl trace $state } + +lappend _telnet_autocomplete_skip "telnet_port" +proc "telnet_port" {args} { + echo "DEPRECATED! use 'telnet port', not 'telnet_port'" + eval telnet port $args +} diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c index 02d450fbd..a596afef0 100644 --- a/src/server/telnet_server.c +++ b/src/server/telnet_server.c @@ -967,7 +967,6 @@ int telnet_init(char *banner) return ERROR_OK; } -/* daemon configuration command telnet_port */ COMMAND_HANDLER(handle_telnet_port_command) { return CALL_COMMAND_HANDLER(server_pipe_command, &telnet_port); @@ -978,6 +977,19 @@ COMMAND_HANDLER(handle_exit_command) return ERROR_COMMAND_CLOSE_CONNECTION; } +static const struct command_registration telnet_subcommand_handlers[] = { + { + .name = "port", + .handler = handle_telnet_port_command, + .mode = COMMAND_CONFIG, + .help = "Specify port on which to listen " + "for incoming telnet connections. " + "Read help on 'gdb port'.", + .usage = "[port_num]", + }, + COMMAND_REGISTRATION_DONE +}; + static const struct command_registration telnet_command_handlers[] = { { .name = "exit", @@ -987,13 +999,11 @@ static const struct command_registration telnet_command_handlers[] = { .help = "exit telnet session", }, { - .name = "telnet_port", - .handler = handle_telnet_port_command, + .name = "telnet", + .chain = telnet_subcommand_handlers, .mode = COMMAND_CONFIG, - .help = "Specify port on which to listen " - "for incoming telnet connections. " - "Read help on 'gdb port'.", - .usage = "[port_num]", + .help = "telnet commands", + .usage = "", }, COMMAND_REGISTRATION_DONE }; diff --git a/src/svf/svf.c b/src/svf/svf.c index dd3d5175c..470889948 100644 --- a/src/svf/svf.c +++ b/src/svf/svf.c @@ -932,7 +932,7 @@ static int svf_check_tdo(void) index_var = svf_check_tdo_para[i].buffer_offset; len = svf_check_tdo_para[i].bit_len; if ((svf_check_tdo_para[i].enabled) - && buf_cmp_mask(&svf_tdi_buffer[index_var], &svf_tdo_buffer[index_var], + && !buf_eq_mask(&svf_tdi_buffer[index_var], &svf_tdo_buffer[index_var], &svf_mask_buffer[index_var], len)) { LOG_ERROR("tdo check error at line %d", svf_check_tdo_para[i].line_num); diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 6a70b2ddf..f0d486f58 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -193,6 +193,20 @@ static int aarch64_mmu_modify(struct target *target, int enable) return retval; } +static int aarch64_read_prsr(struct target *target, uint32_t *prsr) +{ + struct armv8_common *armv8 = target_to_armv8(target); + int retval; + + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_PRSR, prsr); + if (retval != ERROR_OK) + return retval; + + armv8->sticky_reset |= *prsr & PRSR_SR; + return ERROR_OK; +} + /* * Basic debug access, very low level assumes state is saved */ @@ -213,8 +227,7 @@ static int aarch64_init_debug_access(struct target *target) /* Clear Sticky Power Down status Bit in PRSR to enable access to the registers in the Core Power Domain */ - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_PRSR, &dummy); + retval = aarch64_read_prsr(target, &dummy); if (retval != ERROR_OK) return retval; @@ -281,12 +294,10 @@ static int aarch64_set_dscr_bits(struct target *target, unsigned long bit_mask, static int aarch64_check_state_one(struct target *target, uint32_t mask, uint32_t val, int *p_result, uint32_t *p_prsr) { - struct armv8_common *armv8 = target_to_armv8(target); uint32_t prsr; int retval; - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_PRSR, &prsr); + retval = aarch64_read_prsr(target, &prsr); if (retval != ERROR_OK) return retval; @@ -506,16 +517,28 @@ static int update_halt_gdb(struct target *target, enum target_debug_reason debug static int aarch64_poll(struct target *target) { + struct armv8_common *armv8 = target_to_armv8(target); enum target_state prev_target_state; int retval = ERROR_OK; - int halted; + uint32_t prsr; - retval = aarch64_check_state_one(target, - PRSR_HALT, PRSR_HALT, &halted, NULL); + retval = aarch64_read_prsr(target, &prsr); if (retval != ERROR_OK) return retval; - if (halted) { + if (armv8->sticky_reset) { + armv8->sticky_reset = false; + if (target->state != TARGET_RESET) { + target->state = TARGET_RESET; + LOG_TARGET_INFO(target, "external reset detected"); + if (armv8->arm.core_cache) { + register_cache_invalidate(armv8->arm.core_cache); + register_cache_invalidate(armv8->arm.core_cache->next); + } + } + } + + if (prsr & PRSR_HALT) { prev_target_state = target->state; if (prev_target_state != TARGET_HALTED) { enum target_debug_reason debug_reason = target->debug_reason; @@ -546,8 +569,11 @@ static int aarch64_poll(struct target *target) break; } } - } else + } else if (prsr & PRSR_RESET) { + target->state = TARGET_RESET; + } else { target->state = TARGET_RUNNING; + } return retval; } @@ -663,8 +689,7 @@ static int aarch64_prepare_restart_one(struct target *target) if (retval == ERROR_OK) { /* clear sticky bits in PRSR, SDR is now 0 */ - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_PRSR, &tmp); + retval = aarch64_read_prsr(target, &tmp); } return retval; diff --git a/src/target/armv8.h b/src/target/armv8.h index f5aa21109..156b5f8bb 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -213,6 +213,8 @@ struct armv8_common { /* True if OpenOCD provides pointer auth related info to GDB */ bool enable_pauth; + bool sticky_reset; + /* last run-control command issued to this target (resume, halt, step) */ enum run_control_op last_run_control_op; diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 7bef955e5..f3dda0287 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -357,8 +357,8 @@ static void select_dmi(struct target *target) select_dmi_via_bscan(target); return; } - if (buf_cmp(target->tap->cur_instr, select_dbus.out_value, - target->tap->ir_length) == 0) + if (buf_eq(target->tap->cur_instr, select_dbus.out_value, + target->tap->ir_length)) return; jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE); }