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 lookupBreakpoint(char *params) {
int n = -1; int addr = -1;
sscanf(params, "%x", &n); sscanf(params, "%x", &addr);
n = lookupBreakpointN(n); int n = lookupBreakpointN(addr);
if (n < 0) { if (n < 0) {
log0("Breakpoint/watch not set at %04X\n", n); log0("Breakpoint/watch not set at %04X\n", addr);
} }
return n; return n;
} }
@@ -777,11 +777,29 @@ void logTooManyBreakpoints() {
log0("All %d breakpoints are already set\n", numbkpts); 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) { void setBreakpoint(int n, unsigned int addr, unsigned int mask, unsigned int mode, int trigger) {
breakpoints[n] = addr & mask; breakpoints[n] = addr & mask;
masks[n] = mask; masks[n] = mask;
modes[n] = mode; modes[n] = mode;
triggers[n] = trigger; triggers[n] = trigger;
// Update the hardware copy of the breakpoints
uploadBreakpoints();
} }
void clearBreakpoint(int n) { void clearBreakpoint(int n) {
@@ -793,6 +811,9 @@ void clearBreakpoint(int n) {
triggers[i] = triggers[i + 1]; triggers[i] = triggers[i + 1];
} }
numbkpts--; numbkpts--;
// Update the hardware copy of the breakpoints
uploadBreakpoints();
} }
// A generic helper that does most of the work of the watch/breakpoint commands // 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; unsigned int mask = 0xFFFF;
int trigger = -1; int trigger = -1;
sscanf(params, "%x %x %x", &addr, &mask, &trigger); sscanf(params, "%x %x %x", &addr, &mask, &trigger);
// First, see if a breakpoint with this address already exists
for (i = 0; i < numbkpts; i++) { for (i = 0; i < numbkpts; i++) {
if (breakpoints[i] == addr) { if (breakpoints[i] == addr) {
if (modes[i] & mode) { if (modes[i] & mode) {
logMode(mode); logMode(mode);
log0(" already set at %04X\n", addr); log0(" already set at %04X\n", addr);
return;
} else { } else {
// Preserve the existing trigger, unless it is overridden // Preserve the existing trigger, unless it is overridden
if (trigger == -1) { if (trigger == -1) {
trigger = triggers[i]; trigger = triggers[i];
} }
logBreakpoint(addr, mode); // Preserve the existing modes
setBreakpoint(i, addr, mask, modes[i] | mode, trigger); mode |= modes[i];
break;
} }
return;
} }
} }
if (numbkpts == MAXBKPTS) { // If existing breakpoint not find, then create a new one
logTooManyBreakpoints(); if (i == numbkpts) {
return; if (numbkpts == MAXBKPTS) {
} logTooManyBreakpoints();
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);
return; 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 * Test Helpers
********************************************************/ ********************************************************/
@@ -921,6 +945,25 @@ void test(unsigned int start, unsigned int end, int data) {
} }
#endif // CPU_EMBEDDED #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 * User Commands
*******************************************/ *******************************************/
@@ -935,7 +978,7 @@ void doCmdHelp(char *params) {
} }
void doCmdStep(char *params) { void doCmdStep(char *params) {
static long instructions = 1; long instructions = 1;
long i; long i;
long j; long j;
sscanf(params, "%ld", &instructions); sscanf(params, "%ld", &instructions);
@@ -950,6 +993,11 @@ void doCmdStep(char *params) {
for (i = 1; i <= instructions; i++) { for (i = 1; i <= instructions; i++) {
// Step the CPU // Step the CPU
hwCmd(CMD_STEP, 0); 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))) { if (i == instructions || (trace && (--j == 0))) {
Delay_us(10); Delay_us(10);
logAddr(); logAddr();
@@ -1302,35 +1350,20 @@ void doCmdNext(char *params) {
logTooManyBreakpoints(); logTooManyBreakpoints();
return; 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); doCmdContinue(params);
} }
void doCmdContinue(char *params) { void doCmdContinue(char *params) {
int i;
int status;
int reset = 0; int reset = 0;
sscanf(params, "%d", &reset); 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) #if defined(CPU_6809)
// Step the 6809, otherwise the breakpoint happends again immediately // Step the 6809, otherwise the breakpoint happends again immediately
hwCmd(CMD_STEP, 0); hwCmd(CMD_STEP, 0);
#endif #endif
// Enable breakpoints
hwCmd(CMD_BRKPT_ENABLE, 1);
// Disable single stepping // Disable single stepping
setSingle(0); setSingle(0);
@@ -1344,32 +1377,12 @@ void doCmdContinue(char *params) {
// Wait for breakpoint to become active // Wait for breakpoint to become active
log0("CPU free running...\n"); log0("CPU free running...\n");
int cont = 1; while (pollForEvents());
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);
log0("Interrupted\n"); log0("Interrupted\n");
// Enable single stepping // Enable single stepping
setSingle(1); setSingle(1);
// Disable breakpoints
hwCmd(CMD_BRKPT_ENABLE, 0);
// Show current instruction // Show current instruction
logAddr(); logAddr();