mirror of
https://github.com/hoglet67/AtomBusMon.git
synced 2025-01-02 23:32:02 +00:00
Added breakpoint functionality
Change-Id: I82b1162249a1bfed2d340361b205340dfbb70d86
This commit is contained in:
parent
30d42b8bd0
commit
10afdff12c
@ -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
|
||||
};
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -78,6 +78,20 @@ architecture behavioral of AtomBusMon is
|
||||
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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user