Added breakpoint functionality

Change-Id: I82b1162249a1bfed2d340361b205340dfbb70d86
This commit is contained in:
David Banks 2015-06-07 17:58:14 +01:00
parent 30d42b8bd0
commit 10afdff12c
3 changed files with 166 additions and 53 deletions

View File

@ -7,10 +7,20 @@
#define CTRL_PORT PORTB
#define CTRL_DDR DDRB
#define CTRL_DIN PINB
// Outputs
#define STEP_MASK 0x01
#define SINGLE_MASK 0x02
#define RESET_MASK 0x04
#define CTRL_MASK (SINGLE_MASK | STEP_MASK | RESET_MASK)
#define BRKPT_ENABLE_MASK 0x08
#define BRKPT_CLOCK_MASK 0x10
#define BRKPT_DATA_MASK 0x20
// Inputs
#define BRKPT_INTERRUPTED_MASK 0x40
#define BRKPT_ACTIVE_MASK 0x80
#define CTRL_MASK (SINGLE_MASK | STEP_MASK | RESET_MASK | BRKPT_ENABLE_MASK | BRKPT_CLOCK_MASK | BRKPT_DATA_MASK)
#define AL_PORT PORTD
#define AL_DIN PIND
@ -22,7 +32,7 @@
#define AH_MASK 0x00
#define AH_DDR DDRE
#define VERSION "0.10"
#define VERSION "0.11"
#define NUMCMDS 10
#define MAXBKPTS 4
@ -43,14 +53,14 @@ unsigned int breakpoints[MAXBKPTS] = {
char *cmdStrings[NUMCMDS] = {
"help",
"reset",
"break",
"continue",
"interrupt",
"address",
"step",
"trace",
"blist",
"bset",
"bclear"
"break",
"bclear",
"continue",
};
#define Delay_us(__us) \
@ -105,34 +115,33 @@ void setSingle(int i) {
single = i;
if (single) {
CTRL_PORT |= SINGLE_MASK;
log0("Single stepping enabled\n");
} else {
CTRL_PORT &= ~SINGLE_MASK;
log0("Single stepping disabled\n");
}
Delay_us(10);
}
void setTrace(long i) {
trace = i;
if (trace) {
log0("Tracing every %ld instructions\n", trace);
log0("Tracing every %ld instructions while single stepping\n", trace);
} else {
log0("Tracing disabled\n");
}
}
void version() {
log0("Atom Bus Monitor version %s\n", VERSION);
log0("Compiled at %s on %s\n",__TIME__,__DATE__);
}
/*******************************************
* Commands
*******************************************/
void notImplemented() {
log0("Not implemented\n");
}
void doCmdHelp(char *params) {
int i;
log0("Atom Bus Monitor version %s\n", VERSION);
version();
log0("Commands:\n");
for (i = 0; i < NUMCMDS; i++) {
log0(" %s\n", cmdStrings[i]);
@ -168,10 +177,11 @@ void doCmdStep(char *params) {
for (i = 1; i <= instructions; i++) {
// Step the 6502
CTRL_PORT &= ~STEP_MASK;
Delay_us(1);
Delay_us(2);
CTRL_PORT |= STEP_MASK;
Delay_us(1);
Delay_us(2);
if (i == instructions || (trace && (--j == 0))) {
Delay_us(10);
doCmdAddr();
j = trace;
}
@ -185,15 +195,11 @@ void doCmdReset(char *params) {
CTRL_PORT &= ~RESET_MASK;
}
void doCmdBreak(char *params) {
setSingle(true);
void doCmdInterrupt(char *params) {
setSingle(1);
doCmdAddr();
}
void doCmdContinue(char *params) {
setSingle(false);
}
void doCmdTrace(char *params) {
long i;
@ -212,7 +218,7 @@ void doCmdBList(char *params) {
}
}
void doCmdBSet(char *params) {
void doCmdBreak(char *params) {
int i;
unsigned int addr;
sscanf(params, "%x", &addr);
@ -221,6 +227,14 @@ void doCmdBSet(char *params) {
doCmdBList(NULL);
return;
}
for (i = 0; i < numbkpts; i++) {
if (breakpoints[i] == addr) {
log0("Breakpoint already set at %04X\n", addr);
doCmdBList(NULL);
return;
}
}
numbkpts++;
for (i = numbkpts - 2; i >= -1; i--) {
if (i == -1 || breakpoints[i] < addr) {
@ -228,10 +242,6 @@ void doCmdBSet(char *params) {
breakpoints[i + 1] = addr;
doCmdBList(NULL);
return;
} else if (breakpoints[i] == addr) {
log0("Breakpoint already set at %04X\n", addr);
doCmdBList(NULL);
return;
} else {
breakpoints[i + 1] = breakpoints[i];
}
@ -240,7 +250,7 @@ void doCmdBSet(char *params) {
void doCmdBClear(char *params) {
int i;
int n;
int n = 0;
sscanf(params, "%d", &n);
if (n >= numbkpts) {
log0("Breakpoint %d not set\n", n);
@ -254,30 +264,89 @@ void doCmdBClear(char *params) {
doCmdBList(NULL);
}
void shiftBreakpointRegister(unsigned int addr) {
int i;
for (i = 0; i < 16; i++) {
CTRL_PORT &= ~BRKPT_CLOCK_MASK;
if (addr & 1) {
CTRL_PORT |= BRKPT_DATA_MASK;
} else {
CTRL_PORT &= ~BRKPT_DATA_MASK;
}
Delay_us(10);
CTRL_PORT |= BRKPT_CLOCK_MASK;
Delay_us(10);
addr >>= 1;
}
}
void doCmdContinue(char *params) {
int i;
int status;
doCmdBList(NULL);
// Disable breakpoints to allow loading
CTRL_PORT &= ~BRKPT_ENABLE_MASK;
// Load breakpoints into comparators
for (i = 0; i < MAXBKPTS; i++) {
shiftBreakpointRegister(i < numbkpts ? breakpoints[i] : 0);
}
// Enable breakpoints
CTRL_PORT |= BRKPT_ENABLE_MASK;
// Disable single stepping
setSingle(0);
// Wait for breakpoint to become active
log0("6502 free running...\n");
do {
status = CTRL_DIN;
} while (!(status & BRKPT_ACTIVE_MASK) && !(status && BRKPT_INTERRUPTED_MASK));
// Output cause
if (status & BRKPT_ACTIVE_MASK) {
log0("Breakpoint hit at ");
} else {
log0("Interrupted at ");
}
doCmdAddr();
// Enable single stepping
setSingle(1);
// Disable breakpoints
CTRL_PORT &= ~BRKPT_ENABLE_MASK;
}
void initialize() {
CTRL_DDR = CTRL_MASK;
AL_DDR = AL_MASK;
AH_DDR = AH_MASK;
CTRL_PORT &= ~STEP_MASK;
CTRL_PORT &= 0;
Serial_Init(57600,57600);
lcd_init();
lcd_puts("Addr: xxxx");
log0("Atom Bus Monitor\n");
setSingle(false);
setTrace(0);
version();
setSingle(1);
setTrace(1);
log0("6502 paused...\n");
doCmdAddr();
}
void (*cmdFuncs[NUMCMDS])(char *params) = {
doCmdHelp,
doCmdReset,
doCmdBreak,
doCmdContinue,
doCmdInterrupt,
doCmdAddr,
doCmdStep,
doCmdTrace,
doCmdBList,
doCmdBSet,
doCmdBClear
doCmdBreak,
doCmdBClear,
doCmdContinue
};

View File

@ -185,11 +185,9 @@ void Serial_Init(const uint32_t BaudRate0,
cls(0);
cls(1);
log0("stdio initialised\n");
log0("compiled at %s on %s\n",__TIME__,__DATE__);
log0("SerialPort0\n");
log1("SerialPort1\n");
// log0("stdio initialised\n");
// log0("SerialPort0\n");
// log1("SerialPort1\n");
}
#ifdef USE_HEXDUMP

View File

@ -77,7 +77,21 @@ architecture behavioral of AtomBusMon is
signal step : std_logic;
signal step1 : std_logic;
signal step2 : std_logic;
signal brkpt_enable : std_logic;
signal brkpt_clock : std_logic;
signal brkpt_clock1 : std_logic;
signal brkpt_clock2 : std_logic;
signal brkpt_data : std_logic;
signal brkpt_active : std_logic;
signal brkpt_active1 : std_logic;
signal brkpt_0 : std_logic_vector(15 downto 0);
signal brkpt_1 : std_logic_vector(15 downto 0);
signal brkpt_2 : std_logic_vector(15 downto 0);
signal brkpt_3 : std_logic_vector(15 downto 0);
signal brkpt_reg : std_logic_vector(63 downto 0);
begin
inst_dcm5 : entity work.DCM0 port map(
@ -125,11 +139,23 @@ begin
portaout(6) => lcd_db_out(6),
portaout(7) => lcd_db_out(7),
portbin => (others => '0'),
portbin(0) => '0',
portbin(1) => '0',
portbin(2) => '0',
portbin(3) => '0',
portbin(4) => '0',
portbin(5) => '0',
portbin(6) => sw1,
portbin(7) => brkpt_active1,
portbout(0) => step,
portbout(1) => single,
portbout(2) => reset,
portbout(7 downto 3) => open,
portbout(3) => brkpt_enable,
portbout(4) => brkpt_clock,
portbout(5) => brkpt_data,
portbout(6) => open,
portbout(7) => open,
portdin => addr_inst(7 downto 0),
portdout => open,
@ -149,9 +175,9 @@ begin
lcd_db <= lcd_db_out when lcd_rw_int = '0' else (others => 'Z');
lcd_db_in <= lcd_db;
led3 <= dy_counter(24); -- red
led6 <= dy_counter(24); -- red
led8 <= not sw1; -- green
led3 <= '0'; -- red
led6 <= '0'; -- red
led8 <= not brkpt_active; -- green
nrst_avr <= nsw2;
@ -160,26 +186,46 @@ begin
dy_data(1) <= hex & "0000" & Addr(7 downto 4);
dy_data(2) <= hex & "0000" & "00" & (not nsw2) & sw1;
brkpt_0 <= brkpt_reg(15 downto 0);
brkpt_1 <= brkpt_reg(31 downto 16);
brkpt_2 <= brkpt_reg(47 downto 32);
brkpt_3 <= brkpt_reg(63 downto 48);
brkpt_active <= '1' when brkpt_enable = '1' and Sync = '1' and
((Addr = brkpt_0) or (Addr = brkpt_1) or (Addr = brkpt_2) or (Addr = brkpt_3))
else '0';
-- 6502 Control
syncProcess: process (Phi2)
begin
if rising_edge(Phi2) then
step1 <= step;
step2 <= step1;
if ((single = '0') or (step2 = '0' and step1 = '1')) then
Rdy <= '1';
else
Rdy <= not Sync;
end if;
-- Address monitoring
addr_sync <= Addr;
if (Sync = '1') then
addr_inst <= Addr;
end if;
-- Reset
if (reset = '1') then
nRST <= '0';
else
nRST <= 'Z';
end if;
-- Breakpoints
brkpt_clock1 <= brkpt_clock;
brkpt_clock2 <= brkpt_clock1;
if (brkpt_enable = '0' and brkpt_clock2 = '0' and brkpt_clock1 = '1') then
brkpt_reg <= brkpt_data & brkpt_reg(63 downto 1);
end if;
brkpt_active1 <= brkpt_active;
-- Single Stepping
step1 <= step;
step2 <= step1;
if ((single = '0') or (step2 = '0' and step1 = '1')) then
Rdy <= (not brkpt_active);
else
Rdy <= (not Sync);
end if;
end if;
end process;