# HG changeset patch # User John Tsiombikas # Date 1383429367 -7200 # Node ID 330f8891baed3484fc1110f5075697e6c24ffd2f initial commit diff -r 000000000000 -r 330f8891baed .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Sat Nov 02 23:56:07 2013 +0200 @@ -0,0 +1,6 @@ +\.swp$ +\.o$ +\.hex$ +\.eep$ +\.map$ +^eeprog$ diff -r 000000000000 -r 330f8891baed Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Sat Nov 02 23:56:07 2013 +0200 @@ -0,0 +1,38 @@ +src = $(wildcard *.c) +obj = $(src:.c=.o) +bin = eeprog +hex = $(bin).hex +eep = $(bin).eep + +mcu_gcc = atmega644p +mcu_dude = m644p + +CC = avr-gcc +OBJCOPY = avr-objcopy + +CFLAGS = -O2 -pedantic -Wall -mmcu=$(mcu_gcc) +LDFLAGS = -Wl,-Map,$(bin).map -mmcu=$(mcu_gcc) -Wl,-u,vfprintf -lprintf_flt -lm + +.PHONY: all +all: $(hex) $(eep) + +$(bin): $(obj) + $(CC) -o $@ $(obj) $(LDFLAGS) + +$(hex): $(bin) + $(OBJCOPY) -j .text -j .data -O ihex -R .eeprom $< $@ + +$(eep): $(bin) + $(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@ + +.PHONY: fuses +fuses: + avrdude -c usbtiny -p $(mcu_dude) -U lfuse:w:0xe6:m + +.PHONY: program +program: $(hex) + avrdude -c usbtiny -p $(mcu_dude) -e -U flash:w:$(hex) + +.PHONY: clean +clean: + rm -f $(bin) $(obj) $(hex) $(eep) $(bin).map diff -r 000000000000 -r 330f8891baed eeprog.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/eeprog.c Sat Nov 02 23:56:07 2013 +0200 @@ -0,0 +1,230 @@ +/* HW setup: + * EEPROM interface: + * Data bus [0, 7]: Port C + * Address bus [0, 7]: Port A + * [8, 10]: Port B [0, 2] + * ~OE: Port D [6] + * ~WE: Port D [7] + * + * Serial comm: + * TX: Port D [3] (TXD1) + * RX: Port D [2] (RXD1) + * + * 14.7456 MHz crystal connected to XTAL1/XTAL2 + */ + +#include +#include +#include +#include +#include +#include + +#define TIMER_OFF 0 +#define PRESCL_1 1 +#define PRESCL_8 2 +#define PRESCL_64 3 +#define PRESCL_256 4 +#define PRESCL_1024 5 +#define TIMER_EXT_FALL 6 +#define TIMER_EXT_RISE 7 + +/* 1mhz internal osc */ +/*#define CLOCK_FREQ 1000000*/ +/* 14.7456 MHz crystal osc */ +#define CLOCK_FREQ 14745600 +/* 4 MHz crystal osc */ +/*#define CLOCK_FREQ 4000000*/ + +#define BAUD 9600 +#define UBRR_VAL (CLOCK_FREQ / 16 / BAUD - 1) + +#define SEC_TICKS (CLOCK_FREQ / 256 / 256) + +void init_serial(void); +void init_timer(void); + +int uart_send_char(char c, FILE *fp); +int uart_get_char(FILE *fp); + +void runcmd(const char *cmd); + +#define BUF_SZ 32 +static char outbuf[BUF_SZ]; +static volatile int out_rd, out_wr; + +static char inbuf[BUF_SZ]; +static volatile int in_rd, in_wr; + +static char linebuf[64]; +static int line_cidx; + +static FILE std_stream = FDEV_SETUP_STREAM(uart_send_char, uart_get_char, _FDEV_SETUP_RW); + +int main(void) +{ + stdin = stdout = stderr = &std_stream; + + /* port B is our LED output */ + DDRB = 0xff; + PORTB = 0; + + init_timer(); + init_serial(); + sei(); + + fputs("eeprom programmer\n> ", stdout); + + for(;;) { + int c = getchar(); + putchar(c); /* echo back */ + + if(c == '\n') { + linebuf[line_cidx] = 0; + line_cidx = 0; + runcmd(linebuf); + + fputs("> ", stdout); + + } else if(line_cidx < sizeof linebuf - 1) { + linebuf[line_cidx++] = c; + } + } + + return 0; +} + +unsigned char peek(unsigned int addr) +{ + return 42; +} + +void poke(unsigned int addr, unsigned char data) +{ +} + +void init_serial(void) +{ + power_usart0_enable(); + + /* make sure RX (D0) is input and TX (D1) is output */ + DDRD = (DDRD & 0xfc) | 2; + + /* set baud generator timer reset value */ + UBRR0H = (unsigned char)(UBRR_VAL >> 8); + UBRR0L = (unsigned char)UBRR_VAL; + + /* - enable receiver and transmitter + * - enable receive interrupt + */ + UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0); + + /* set frame format: 8N1 */ + UCSR0C = (3 << UCSZ00); +} + +#define NEXT_IDX(x) (((x) + 1) % BUF_SZ) +int uart_send_char(char c, FILE *fp) +{ + int next; + + if(c == '\n') { + uart_send_char('\r', fp); + } + + next = NEXT_IDX(out_wr); + while(next == out_rd); + + outbuf[out_wr] = c; + out_wr = next; + + /* enable the Tx data register empty interrupt */ + UCSR0B |= 1 << UDRIE0; + return 0; +} + +int uart_get_char(FILE *fp) +{ + char c; + int next = NEXT_IDX(in_rd); + + while(in_rd == in_wr); + + c = inbuf[in_rd]; + in_rd = next; + return c; +} + +void runcmd(const char *cmd) +{ + unsigned int addr = 0; + unsigned int data = 0; + + if(strcmp(cmd, "info") == 0) { + printf("Atmel ATmega644 8bit AVR microcontroller running at %ld Hz\n", CLOCK_FREQ); + } else if(sscanf(cmd, "peek %u", &addr) == 1) { + printf("%x\n", (unsigned int)peek(addr)); + } else if(sscanf(cmd, "poke %u , %x", &addr, &data) == 2) { + poke(addr, data); + } else if(strcmp(cmd, "help") == 0) { + + puts("Available commands:"); + puts(" info print system info"); + puts(" peek read a byte from a memory address"); + puts(" poke , write a byte to a memory address"); + puts(" help print this help screen"); + + } else { + printf("unknown command: %s\n", cmd); + } +} + +void init_timer(void) +{ + power_timer0_enable(); + + TCCR0A = 0; + TCCR0B = PRESCL_256; + + /* enable timer overflow interrupt */ + TIMSK0 = 1; +} + +ISR(TIMER0_OVF_vect) +{ + volatile static int ticks; + + if(++ticks >= SEC_TICKS) { + int val = PORTB; + if(val & 1) { + PORTB &= ~1; + } else { + PORTB |= 1; + } + ticks = 0; + } +} + +ISR(USART0_RX_vect) +{ + char c = UDR0; + + if(c == '\r') { + c = '\n'; + } + + inbuf[in_wr] = c; + in_wr = NEXT_IDX(in_wr); +} + +/* USART Tx data register empty (can send more data) */ +ISR(USART0_UDRE_vect) +{ + if(out_rd != out_wr) { + UDR0 = outbuf[out_rd]; + out_rd = NEXT_IDX(out_rd); + } else { + /* no more data to send for now, disable the interrupt */ + UCSR0B &= ~(1 << UDRIE0); + } +}