David Brownell <david-b@pacbell.net> Add "cortex_m3 vector_catch" command and docs. One minor

issue with this is that the core debug support uses this
mechanism, then trashes its state over reset.  Users can
Work around that (for now) by re-assigning the desired
config after reset.

Also fixes "target halted due to target-not-halted" goof.
When we can't describe the reason using OpenOCD's limited
vocabulary, say "reason undefined" instead of saying it's
not halted.

git-svn-id: svn://svn.berlios.de/openocd/trunk@2588 b42882b7-edfa-0310-969c-e2dbd0fdcd60
__archive__
oharboe 2009-08-18 10:25:28 +00:00
parent a4c7e2dd96
commit ed22097a55
3 changed files with 115 additions and 4 deletions

View File

@ -737,7 +737,9 @@ the @command{reset init} command will interfere with debugging
early boot code, which performs some of the same actions early boot code, which performs some of the same actions
that the @code{reset-init} event handler does. that the @code{reset-init} event handler does.
Likewise, the @command{arm9tdmi vector_catch} command (or Likewise, the @command{arm9tdmi vector_catch} command (or
its @command{xscale vector_catch} sibling) can be a timesaver @cindex vector_catch
its siblings @command{xscale vector_catch}
and @command{cortex_m3 vector_catch}) can be a timesaver
during some debug sessions, but don't make everyone use that either. during some debug sessions, but don't make everyone use that either.
Keep those kinds of debugging aids in your user config file, Keep those kinds of debugging aids in your user config file,
along with messaging and tracing setup. along with messaging and tracing setup.
@ -4738,6 +4740,7 @@ Such cores include the ARM920T, ARM926EJ-S, and ARM966.
@anchor{arm9tdmi vector_catch} @anchor{arm9tdmi vector_catch}
@deffn Command {arm9tdmi vector_catch} [@option{all}|@option{none}|list] @deffn Command {arm9tdmi vector_catch} [@option{all}|@option{none}|list]
@cindex vector_catch
Vector Catch hardware provides a sort of dedicated breakpoint Vector Catch hardware provides a sort of dedicated breakpoint
for hardware events such as reset, interrupt, and abort. for hardware events such as reset, interrupt, and abort.
You can use this to conserve normal breakpoint resources, You can use this to conserve normal breakpoint resources,
@ -4927,6 +4930,7 @@ The image @var{type} may be one of
@anchor{xscale vector_catch} @anchor{xscale vector_catch}
@deffn Command {xscale vector_catch} [mask] @deffn Command {xscale vector_catch} [mask]
@cindex vector_catch
Display a bitmask showing the hardware vectors to catch. Display a bitmask showing the hardware vectors to catch.
If the optional parameter is provided, first set the bitmask to that value. If the optional parameter is provided, first set the bitmask to that value.
@end deffn @end deffn
@ -5016,6 +5020,33 @@ Disassembles @var{count} Thumb2 instructions starting at @var{address}.
Control masking (disabling) interrupts during target step/resume. Control masking (disabling) interrupts during target step/resume.
@end deffn @end deffn
@deffn Command {cortex_m3 vector_catch} [@option{all}|@option{none}|list]
@cindex vector_catch
Vector Catch hardware provides dedicated breakpoints
for certain hardware events.
Parameters request interception of
@option{all} of these hardware event vectors,
@option{none} of them,
or one or more of the following:
@option{hard_err} for a HardFault exception;
@option{mm_err} for a MemManage exception;
@option{bus_err} for a BusFault exception;
@option{irq_err},
@option{state_err},
@option{chk_err}, or
@option{nocp_err} for various UsageFault exceptions; or
@option{reset}.
If NVIC setup code does not enable them,
MemManage, BusFault, and UsageFault exceptions
are mapped to HardFault.
UsageFault checks for
divide-by-zero and unaligned access
must also be explicitly enabled.
This finishes by listing the current vector catch configuration.
@end deffn
@anchor{Software Debug Messages and Tracing} @anchor{Software Debug Messages and Tracing}
@section Software Debug Messages and Tracing @section Software Debug Messages and Tracing
@cindex Linux-ARM DCC support @cindex Linux-ARM DCC support

View File

@ -37,6 +37,9 @@
#include "arm_disassembler.h" #include "arm_disassembler.h"
#define ARRAY_SIZE(x) ((int)(sizeof(x)/sizeof((x)[0])))
/* cli handling */ /* cli handling */
int cortex_m3_register_commands(struct command_context_s *cmd_ctx); int cortex_m3_register_commands(struct command_context_s *cmd_ctx);
int handle_cortex_m3_mask_interrupts_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int handle_cortex_m3_mask_interrupts_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
@ -174,7 +177,7 @@ int cortex_m3_clear_halt(target_t *target)
/* Read Debug Fault Status Register */ /* Read Debug Fault Status Register */
mem_ap_read_atomic_u32(swjdp, NVIC_DFSR, &cortex_m3->nvic_dfsr); mem_ap_read_atomic_u32(swjdp, NVIC_DFSR, &cortex_m3->nvic_dfsr);
/* Write Debug Fault Status Register to enable processing to resume ?? Try with and without this !! */ /* Clear Debug Fault Status */
mem_ap_write_atomic_u32(swjdp, NVIC_DFSR, cortex_m3->nvic_dfsr); mem_ap_write_atomic_u32(swjdp, NVIC_DFSR, cortex_m3->nvic_dfsr);
LOG_DEBUG(" NVIC_DFSR 0x%" PRIx32 "", cortex_m3->nvic_dfsr); LOG_DEBUG(" NVIC_DFSR 0x%" PRIx32 "", cortex_m3->nvic_dfsr);
@ -307,8 +310,6 @@ int cortex_m3_examine_debug_reason(target_t *target)
if ((target->debug_reason != DBG_REASON_DBGRQ) if ((target->debug_reason != DBG_REASON_DBGRQ)
&& (target->debug_reason != DBG_REASON_SINGLESTEP)) && (target->debug_reason != DBG_REASON_SINGLESTEP))
{ {
/* INCOMPLETE */
if (cortex_m3->nvic_dfsr & DFSR_BKPT) if (cortex_m3->nvic_dfsr & DFSR_BKPT)
{ {
target->debug_reason = DBG_REASON_BREAKPOINT; target->debug_reason = DBG_REASON_BREAKPOINT;
@ -317,6 +318,10 @@ int cortex_m3_examine_debug_reason(target_t *target)
} }
else if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP) else if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP)
target->debug_reason = DBG_REASON_WATCHPOINT; target->debug_reason = DBG_REASON_WATCHPOINT;
else if (cortex_m3->nvic_dfsr & DFSR_VCATCH)
target->debug_reason = DBG_REASON_BREAKPOINT;
else /* EXTERNAL, HALTED, DWTTRAP w/o BKPT */
target->debug_reason = DBG_REASON_UNDEFINED;
} }
return ERROR_OK; return ERROR_OK;
@ -1703,6 +1708,73 @@ handle_cortex_m3_disassemble_command(struct command_context_s *cmd_ctx,
return ERROR_OK; return ERROR_OK;
} }
static const struct {
char name[10];
unsigned mask;
} vec_ids[] = {
{ "hard_err", VC_HARDERR, },
{ "int_err", VC_INTERR, },
{ "bus_err", VC_BUSERR, },
{ "state_err", VC_STATERR, },
{ "chk_err", VC_CHKERR, },
{ "nocp_err", VC_NOCPERR, },
{ "mm_err", VC_MMERR, },
{ "reset", VC_CORERESET, },
};
static int
handle_cortex_m3_vector_catch_command(struct command_context_s *cmd_ctx,
char *cmd, char **argv, int argc)
{
target_t *target = get_current_target(cmd_ctx);
armv7m_common_t *armv7m = target->arch_info;
swjdp_common_t *swjdp = &armv7m->swjdp_info;
uint32_t demcr = 0;
int i;
mem_ap_read_atomic_u32(swjdp, DCB_DEMCR, &demcr);
if (argc > 0) {
unsigned catch = 0;
if (argc == 1) {
if (strcmp(argv[0], "all") == 0) {
catch = VC_HARDERR | VC_INTERR | VC_BUSERR
| VC_STATERR | VC_CHKERR | VC_NOCPERR
| VC_MMERR | VC_CORERESET;
goto write;
} else if (strcmp(argv[0], "none") == 0) {
goto write;
}
}
while (argc-- > 0) {
for (i = 0; i < ARRAY_SIZE(vec_ids); i++) {
if (strcmp(argv[argc], vec_ids[i].name) != 0)
continue;
catch |= vec_ids[i].mask;
break;
}
if (i == ARRAY_SIZE(vec_ids)) {
LOG_ERROR("No CM3 vector '%s'", argv[argc]);
return ERROR_INVALID_ARGUMENTS;
}
}
write:
demcr &= ~0xffff;
demcr |= catch;
/* write, but don't assume it stuck */
mem_ap_write_u32(swjdp, DCB_DEMCR, demcr);
mem_ap_read_atomic_u32(swjdp, DCB_DEMCR, &demcr);
}
for (i = 0; i < ARRAY_SIZE(vec_ids); i++)
command_print(cmd_ctx, "%9s: %s", vec_ids[i].name,
(demcr & vec_ids[i].mask) ? "catch" : "ignore");
return ERROR_OK;
}
int cortex_m3_register_commands(struct command_context_s *cmd_ctx) int cortex_m3_register_commands(struct command_context_s *cmd_ctx)
{ {
int retval; int retval;
@ -1719,6 +1791,9 @@ int cortex_m3_register_commands(struct command_context_s *cmd_ctx)
register_command(cmd_ctx, cortex_m3_cmd, "maskisr", register_command(cmd_ctx, cortex_m3_cmd, "maskisr",
handle_cortex_m3_mask_interrupts_command, COMMAND_EXEC, handle_cortex_m3_mask_interrupts_command, COMMAND_EXEC,
"mask cortex_m3 interrupts ['on'|'off']"); "mask cortex_m3 interrupts ['on'|'off']");
register_command(cmd_ctx, cortex_m3_cmd, "vector_catch",
handle_cortex_m3_vector_catch_command, COMMAND_EXEC,
"catch hardware vectors ['all'|'none'|<list>]");
return retval; return retval;
} }

View File

@ -80,7 +80,12 @@ extern char* cortex_m3_state_strings[];
/* DCB_DEMCR bit and field definitions */ /* DCB_DEMCR bit and field definitions */
#define TRCENA (1 << 24) #define TRCENA (1 << 24)
#define VC_HARDERR (1 << 10) #define VC_HARDERR (1 << 10)
#define VC_INTERR (1 << 9)
#define VC_BUSERR (1 << 8) #define VC_BUSERR (1 << 8)
#define VC_STATERR (1 << 7)
#define VC_CHKERR (1 << 6)
#define VC_NOCPERR (1 << 5)
#define VC_MMERR (1 << 4)
#define VC_CORERESET (1 << 0) #define VC_CORERESET (1 << 0)
#define NVIC_ICTR 0xE000E004 #define NVIC_ICTR 0xE000E004