Firmware: show break/watch points when stepping (big change)

Change-Id: I106f3c6ac860d1f1bbae312b154491b5f8a0f86f
This commit is contained in:
David Banks 2019-10-31 15:23:34 +00:00
parent c2e80e2e4c
commit 74116942fc

View File

@ -742,11 +742,11 @@ int lookupBreakpointN(int n) {
}
int lookupBreakpoint(char *params) {
int n = -1;
sscanf(params, "%x", &n);
n = lookupBreakpointN(n);
int addr = -1;
sscanf(params, "%x", &addr);
int n = lookupBreakpointN(addr);
if (n < 0) {
log0("Breakpoint/watch not set at %04X\n", n);
log0("Breakpoint/watch not set at %04X\n", addr);
}
return n;
}
@ -777,11 +777,29 @@ void logTooManyBreakpoints() {
log0("All %d breakpoints are already set\n", numbkpts);
}
void uploadBreakpoints() {
int i;
// Disable breakpoints to allow loading
hwCmd(CMD_BRKPT_ENABLE, 0);
// Load breakpoints into comparators
for (i = 0; i < numbkpts; i++) {
shiftBreakpointRegister(breakpoints[i], masks[i], modes[i], triggers[i]);
}
for (i = numbkpts; i < MAXBKPTS; i++) {
shiftBreakpointRegister(0, 0, 0, 0);
}
// Enable breakpoints
hwCmd(CMD_BRKPT_ENABLE, 1);
}
void setBreakpoint(int n, unsigned int addr, unsigned int mask, unsigned int mode, int trigger) {
breakpoints[n] = addr & mask;
masks[n] = mask;
modes[n] = mode;
triggers[n] = trigger;
// Update the hardware copy of the breakpoints
uploadBreakpoints();
}
void clearBreakpoint(int n) {
@ -793,6 +811,9 @@ void clearBreakpoint(int n) {
triggers[i] = triggers[i + 1];
}
numbkpts--;
// Update the hardware copy of the breakpoints
uploadBreakpoints();
}
// A generic helper that does most of the work of the watch/breakpoint commands
@ -802,46 +823,49 @@ void genericBreakpoint(char *params, unsigned int mode) {
unsigned int mask = 0xFFFF;
int trigger = -1;
sscanf(params, "%x %x %x", &addr, &mask, &trigger);
// First, see if a breakpoint with this address already exists
for (i = 0; i < numbkpts; i++) {
if (breakpoints[i] == addr) {
if (modes[i] & mode) {
logMode(mode);
log0(" already set at %04X\n", addr);
return;
} else {
// Preserve the existing trigger, unless it is overridden
if (trigger == -1) {
trigger = triggers[i];
}
logBreakpoint(addr, mode);
setBreakpoint(i, addr, mask, modes[i] | mode, trigger);
// Preserve the existing modes
mode |= modes[i];
break;
}
return;
}
}
if (numbkpts == MAXBKPTS) {
logTooManyBreakpoints();
return;
}
numbkpts++;
// New breakpoint, so if trigger not specified, set to ALWAYS
if (trigger == -1) {
trigger = TRIGGER_ALWAYS;
}
for (i = numbkpts - 2; i >= -1; i--) {
if (i == -1 || breakpoints[i] < addr) {
logBreakpoint(addr, mode);
setBreakpoint(i + 1, addr, mask, mode, trigger);
// If existing breakpoint not find, then create a new one
if (i == numbkpts) {
if (numbkpts == MAXBKPTS) {
logTooManyBreakpoints();
return;
} else {
breakpoints[i + 1] = breakpoints[i];
masks[i + 1] = masks[i];
modes[i + 1] = modes[i];
triggers[i + 1] = triggers[i];
}
// New breakpoint, so if trigger not specified, set to ALWAYS
if (trigger == -1) {
trigger = TRIGGER_ALWAYS;
}
// Maintain the breakpoints in order of address
while (i > 0 && breakpoints[i - 1] > addr) {
breakpoints[i] = breakpoints[i - 1];
masks[i] = masks[i - 1];
modes[i] = modes[i - 1];
triggers[i] = triggers[i - 1];
i--;
}
numbkpts++;
}
// At this point, i contains the index of the new breakpoint
logBreakpoint(addr, mode);
setBreakpoint(i, addr, mask, mode, trigger);
}
/********************************************************
* Test Helpers
********************************************************/
@ -921,6 +945,25 @@ void test(unsigned int start, unsigned int end, int data) {
}
#endif // CPU_EMBEDDED
int pollForEvents() {
int cont = 1;
while (STATUS_DIN & BW_ACTIVE_MASK) {
cont = logDetails();
hwCmd(CMD_WATCH_READ, 0);
Delay_us(10);
}
if (STATUS_DIN & INTERRUPTED_MASK) {
cont = 0;
}
if (Serial_ByteRecieved0()) {
// Interrupt on a return, ignore other characters
if (Serial_RxByte0() == 13) {
cont = 0;
}
}
return cont;
}
/*******************************************
* User Commands
*******************************************/
@ -935,7 +978,7 @@ void doCmdHelp(char *params) {
}
void doCmdStep(char *params) {
static long instructions = 1;
long instructions = 1;
long i;
long j;
sscanf(params, "%ld", &instructions);
@ -950,6 +993,11 @@ void doCmdStep(char *params) {
for (i = 1; i <= instructions; i++) {
// Step the CPU
hwCmd(CMD_STEP, 0);
// Output any watch/breakpoint messages
if (!pollForEvents()) {
log0("Interrupted after %ld instructions\n", i);
i = instructions;
}
if (i == instructions || (trace && (--j == 0))) {
Delay_us(10);
logAddr();
@ -1302,35 +1350,20 @@ void doCmdNext(char *params) {
logTooManyBreakpoints();
return;
}
setBreakpoint(numbkpts++, nextAddr, 0xffff, (1 << BRKPT_EXEC) | (1 << TRANSIENT), TRIGGER_ALWAYS);
numbkpts++;
setBreakpoint(numbkpts - 1, nextAddr, 0xffff, (1 << BRKPT_EXEC) | (1 << TRANSIENT), TRIGGER_ALWAYS);
doCmdContinue(params);
}
void doCmdContinue(char *params) {
int i;
int status;
int reset = 0;
sscanf(params, "%d", &reset);
// Disable breakpoints to allow loading
hwCmd(CMD_BRKPT_ENABLE, 0);
// Load breakpoints into comparators
for (i = 0; i < numbkpts; i++) {
shiftBreakpointRegister(breakpoints[i], masks[i], modes[i], triggers[i]);
}
for (i = numbkpts; i < MAXBKPTS; i++) {
shiftBreakpointRegister(0, 0, 0, 0);
}
#if defined(CPU_6809)
// Step the 6809, otherwise the breakpoint happends again immediately
hwCmd(CMD_STEP, 0);
#endif
// Enable breakpoints
hwCmd(CMD_BRKPT_ENABLE, 1);
// Disable single stepping
setSingle(0);
@ -1344,32 +1377,12 @@ void doCmdContinue(char *params) {
// Wait for breakpoint to become active
log0("CPU free running...\n");
int cont = 1;
do {
status = STATUS_DIN;
if (status & BW_ACTIVE_MASK) {
cont = logDetails();
hwCmd(CMD_WATCH_READ, 0);
}
if (status & INTERRUPTED_MASK) {
cont = 0;
}
if (Serial_ByteRecieved0()) {
// Interrupt on a return, ignore other characters
if (Serial_RxByte0() == 13) {
cont = 0;
}
}
Delay_us(10);
} while (cont);
while (pollForEvents());
log0("Interrupted\n");
// Enable single stepping
setSingle(1);
// Disable breakpoints
hwCmd(CMD_BRKPT_ENABLE, 0);
// Show current instruction
logAddr();