#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
+#include <util/delay.h>
#include "serial.h"
/* pin assignments
static void end_prog(void);
static void write_ram(uint16_t addr, uint8_t val);
static uint8_t read_ram(uint16_t addr);
+static void dbg_setup_read(uint16_t addr);
static void set_data_bus(unsigned char val);
+static void release_data_bus(void);
static void set_addr_bus(uint16_t addr);
static void sys_reset(void);
static inline void iodelay(void);
int main(void)
{
- /* SPI (SS/MOSI/SCK) are outputs, as are the low 2 data bus bits */
- DDRB = PB_SS | PB_MOSI | PB_SCK | 3;
+ /* SPI (SS/MOSI/SCK) are outputs */
+ DDRB = PB_SS | PB_MOSI | PB_SCK;
PORTB = PB_SS; /* drive SS high when not in programming mode */
DDRC = 0xff; /* control signals are all outputs */
PORTC = PC_CS | PC_WE | PC_OE | PC_SYSRST;
- DDRD = 0xff; /* always drive the (high bits of the) data bus */
+ DDRD = 0; /* tri-state the data bus by default (high 6 bits, low 2 are in DDRB) */
PORTD = 0;
/* disable all pullups */
printf("OK %d\n", (int)data);
break;
+ case 'R':
+ if(!progmode) {
+ puts("ERR not in programming mode");
+ break;
+ }
+ dbg_setup_read(addr);
+ printf("OK set up read from %x\n", (unsigned int)addr);
+ break;
+
+ case 'A':
+ if(!progmode) {
+ puts("ERR not in programming mode");
+ break;
+ }
+ addr = strtol(input + 1, &endp, 0);
+ set_addr_bus(addr);
+ printf("OK DBG address %x\n", (unsigned int)addr);
+ break;
+
case '?':
puts("OK command help");
puts(" e 0|1: turn echo on/off");
puts(" w <data>: store data byte and increment address (0-255)");
puts(" r: read data byte and increment address");
puts(" ?: print command help");
+ printf("Currently in %s mode\n", progmode ? "programming" : "boot");
break;
default:
static void end_prog(void)
{
- /* PGM low and return reset high */
+ /* make extra sure we don't drive the data bus */
+ release_data_bus();
+
+ /* PGM low and return reset and SS high */
+ PORTB |= PB_SS;
PORTC &= ~PC_PGM;
- PORTC |= PC_SYSRST;
+ PORTC |= PC_SYSRST | PC_CS | PC_OE;
progmode = 0;
}
iodelay();
PORTC |= PC_CS;
PORTC |= PC_WE;
+ release_data_bus();
}
static uint8_t read_ram(uint16_t addr)
PORTC |= PC_WE;
PORTC &= ~(PC_CS | PC_OE);
iodelay();
- val = (PORTD & 0xfe) | (PORTB & 3);
+ val = (PIND & 0xfc) | (PINB & 3);
PORTC |= PC_CS | PC_OE;
return val;
}
+static void dbg_setup_read(uint16_t addr)
+{
+ set_addr_bus(addr);
+ PORTC |= PC_WE;
+ PORTC &= ~(PC_CS | PC_OE);
+}
+
+
static void set_data_bus(unsigned char val)
{
- PORTB = (PORTB & 0xfe) | (val & 3);
- PORTC = val;
+ /* drive the data bus */
+ DDRD = 0xff;
+ DDRB |= 3;
+ PORTB = (PORTB & 0xfc) | (val & 3);
+ PORTD = val;
+}
+
+static void release_data_bus(void)
+{
+ DDRD = 0;
+ DDRB &= 0xfc;
+
+ PORTD = 0;
+ PORTB &= 0xfc;
}
static void set_addr_bus(uint16_t addr)
{
PORTB &= ~PB_SS;
- SPDR = (uint8_t)addr;
- while(!(SPSR & (1 << SPIF)));
SPDR = (uint8_t)(addr >> 8);
while(!(SPSR & (1 << SPIF)));
+ SPDR = (uint8_t)addr;
+ while(!(SPSR & (1 << SPIF)));
PORTB |= PB_SS;
iodelay();
static void sys_reset(void)
{
PORTC &= ~PC_SYSRST;
- iodelay();
+ _delay_ms(500);
PORTC |= PC_SYSRST;
}