eeprog
changeset 0:330f8891baed tip
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 02 Nov 2013 23:56:07 +0200 |
parents | |
children | |
files | .hgignore Makefile eeprog.c |
diffstat | 3 files changed, 274 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/.hgignore Sat Nov 02 23:56:07 2013 +0200 1.3 @@ -0,0 +1,6 @@ 1.4 +\.swp$ 1.5 +\.o$ 1.6 +\.hex$ 1.7 +\.eep$ 1.8 +\.map$ 1.9 +^eeprog$
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/Makefile Sat Nov 02 23:56:07 2013 +0200 2.3 @@ -0,0 +1,38 @@ 2.4 +src = $(wildcard *.c) 2.5 +obj = $(src:.c=.o) 2.6 +bin = eeprog 2.7 +hex = $(bin).hex 2.8 +eep = $(bin).eep 2.9 + 2.10 +mcu_gcc = atmega644p 2.11 +mcu_dude = m644p 2.12 + 2.13 +CC = avr-gcc 2.14 +OBJCOPY = avr-objcopy 2.15 + 2.16 +CFLAGS = -O2 -pedantic -Wall -mmcu=$(mcu_gcc) 2.17 +LDFLAGS = -Wl,-Map,$(bin).map -mmcu=$(mcu_gcc) -Wl,-u,vfprintf -lprintf_flt -lm 2.18 + 2.19 +.PHONY: all 2.20 +all: $(hex) $(eep) 2.21 + 2.22 +$(bin): $(obj) 2.23 + $(CC) -o $@ $(obj) $(LDFLAGS) 2.24 + 2.25 +$(hex): $(bin) 2.26 + $(OBJCOPY) -j .text -j .data -O ihex -R .eeprom $< $@ 2.27 + 2.28 +$(eep): $(bin) 2.29 + $(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@ 2.30 + 2.31 +.PHONY: fuses 2.32 +fuses: 2.33 + avrdude -c usbtiny -p $(mcu_dude) -U lfuse:w:0xe6:m 2.34 + 2.35 +.PHONY: program 2.36 +program: $(hex) 2.37 + avrdude -c usbtiny -p $(mcu_dude) -e -U flash:w:$(hex) 2.38 + 2.39 +.PHONY: clean 2.40 +clean: 2.41 + rm -f $(bin) $(obj) $(hex) $(eep) $(bin).map
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/eeprog.c Sat Nov 02 23:56:07 2013 +0200 3.3 @@ -0,0 +1,230 @@ 3.4 +/* HW setup: 3.5 + * EEPROM interface: 3.6 + * Data bus [0, 7]: Port C 3.7 + * Address bus [0, 7]: Port A 3.8 + * [8, 10]: Port B [0, 2] 3.9 + * ~OE: Port D [6] 3.10 + * ~WE: Port D [7] 3.11 + * 3.12 + * Serial comm: 3.13 + * TX: Port D [3] (TXD1) 3.14 + * RX: Port D [2] (RXD1) 3.15 + * 3.16 + * 14.7456 MHz crystal connected to XTAL1/XTAL2 3.17 + */ 3.18 + 3.19 +#include <stdio.h> 3.20 +#include <string.h> 3.21 +#include <ctype.h> 3.22 +#include <avr/io.h> 3.23 +#include <avr/interrupt.h> 3.24 +#include <avr/power.h> 3.25 + 3.26 +#define TIMER_OFF 0 3.27 +#define PRESCL_1 1 3.28 +#define PRESCL_8 2 3.29 +#define PRESCL_64 3 3.30 +#define PRESCL_256 4 3.31 +#define PRESCL_1024 5 3.32 +#define TIMER_EXT_FALL 6 3.33 +#define TIMER_EXT_RISE 7 3.34 + 3.35 +/* 1mhz internal osc */ 3.36 +/*#define CLOCK_FREQ 1000000*/ 3.37 +/* 14.7456 MHz crystal osc */ 3.38 +#define CLOCK_FREQ 14745600 3.39 +/* 4 MHz crystal osc */ 3.40 +/*#define CLOCK_FREQ 4000000*/ 3.41 + 3.42 +#define BAUD 9600 3.43 +#define UBRR_VAL (CLOCK_FREQ / 16 / BAUD - 1) 3.44 + 3.45 +#define SEC_TICKS (CLOCK_FREQ / 256 / 256) 3.46 + 3.47 +void init_serial(void); 3.48 +void init_timer(void); 3.49 + 3.50 +int uart_send_char(char c, FILE *fp); 3.51 +int uart_get_char(FILE *fp); 3.52 + 3.53 +void runcmd(const char *cmd); 3.54 + 3.55 +#define BUF_SZ 32 3.56 +static char outbuf[BUF_SZ]; 3.57 +static volatile int out_rd, out_wr; 3.58 + 3.59 +static char inbuf[BUF_SZ]; 3.60 +static volatile int in_rd, in_wr; 3.61 + 3.62 +static char linebuf[64]; 3.63 +static int line_cidx; 3.64 + 3.65 +static FILE std_stream = FDEV_SETUP_STREAM(uart_send_char, uart_get_char, _FDEV_SETUP_RW); 3.66 + 3.67 +int main(void) 3.68 +{ 3.69 + stdin = stdout = stderr = &std_stream; 3.70 + 3.71 + /* port B is our LED output */ 3.72 + DDRB = 0xff; 3.73 + PORTB = 0; 3.74 + 3.75 + init_timer(); 3.76 + init_serial(); 3.77 + sei(); 3.78 + 3.79 + fputs("eeprom programmer\n> ", stdout); 3.80 + 3.81 + for(;;) { 3.82 + int c = getchar(); 3.83 + putchar(c); /* echo back */ 3.84 + 3.85 + if(c == '\n') { 3.86 + linebuf[line_cidx] = 0; 3.87 + line_cidx = 0; 3.88 + runcmd(linebuf); 3.89 + 3.90 + fputs("> ", stdout); 3.91 + 3.92 + } else if(line_cidx < sizeof linebuf - 1) { 3.93 + linebuf[line_cidx++] = c; 3.94 + } 3.95 + } 3.96 + 3.97 + return 0; 3.98 +} 3.99 + 3.100 +unsigned char peek(unsigned int addr) 3.101 +{ 3.102 + return 42; 3.103 +} 3.104 + 3.105 +void poke(unsigned int addr, unsigned char data) 3.106 +{ 3.107 +} 3.108 + 3.109 +void init_serial(void) 3.110 +{ 3.111 + power_usart0_enable(); 3.112 + 3.113 + /* make sure RX (D0) is input and TX (D1) is output */ 3.114 + DDRD = (DDRD & 0xfc) | 2; 3.115 + 3.116 + /* set baud generator timer reset value */ 3.117 + UBRR0H = (unsigned char)(UBRR_VAL >> 8); 3.118 + UBRR0L = (unsigned char)UBRR_VAL; 3.119 + 3.120 + /* - enable receiver and transmitter 3.121 + * - enable receive interrupt 3.122 + */ 3.123 + UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0); 3.124 + 3.125 + /* set frame format: 8N1 */ 3.126 + UCSR0C = (3 << UCSZ00); 3.127 +} 3.128 + 3.129 +#define NEXT_IDX(x) (((x) + 1) % BUF_SZ) 3.130 +int uart_send_char(char c, FILE *fp) 3.131 +{ 3.132 + int next; 3.133 + 3.134 + if(c == '\n') { 3.135 + uart_send_char('\r', fp); 3.136 + } 3.137 + 3.138 + next = NEXT_IDX(out_wr); 3.139 + while(next == out_rd); 3.140 + 3.141 + outbuf[out_wr] = c; 3.142 + out_wr = next; 3.143 + 3.144 + /* enable the Tx data register empty interrupt */ 3.145 + UCSR0B |= 1 << UDRIE0; 3.146 + return 0; 3.147 +} 3.148 + 3.149 +int uart_get_char(FILE *fp) 3.150 +{ 3.151 + char c; 3.152 + int next = NEXT_IDX(in_rd); 3.153 + 3.154 + while(in_rd == in_wr); 3.155 + 3.156 + c = inbuf[in_rd]; 3.157 + in_rd = next; 3.158 + return c; 3.159 +} 3.160 + 3.161 +void runcmd(const char *cmd) 3.162 +{ 3.163 + unsigned int addr = 0; 3.164 + unsigned int data = 0; 3.165 + 3.166 + if(strcmp(cmd, "info") == 0) { 3.167 + printf("Atmel ATmega644 8bit AVR microcontroller running at %ld Hz\n", CLOCK_FREQ); 3.168 + } else if(sscanf(cmd, "peek %u", &addr) == 1) { 3.169 + printf("%x\n", (unsigned int)peek(addr)); 3.170 + } else if(sscanf(cmd, "poke %u , %x", &addr, &data) == 2) { 3.171 + poke(addr, data); 3.172 + } else if(strcmp(cmd, "help") == 0) { 3.173 + 3.174 + puts("Available commands:"); 3.175 + puts(" info print system info"); 3.176 + puts(" peek <addr> read a byte from a memory address"); 3.177 + puts(" poke <addr>, <byte> write a byte to a memory address"); 3.178 + puts(" help print this help screen"); 3.179 + 3.180 + } else { 3.181 + printf("unknown command: %s\n", cmd); 3.182 + } 3.183 +} 3.184 + 3.185 +void init_timer(void) 3.186 +{ 3.187 + power_timer0_enable(); 3.188 + 3.189 + TCCR0A = 0; 3.190 + TCCR0B = PRESCL_256; 3.191 + 3.192 + /* enable timer overflow interrupt */ 3.193 + TIMSK0 = 1; 3.194 +} 3.195 + 3.196 +ISR(TIMER0_OVF_vect) 3.197 +{ 3.198 + volatile static int ticks; 3.199 + 3.200 + if(++ticks >= SEC_TICKS) { 3.201 + int val = PORTB; 3.202 + if(val & 1) { 3.203 + PORTB &= ~1; 3.204 + } else { 3.205 + PORTB |= 1; 3.206 + } 3.207 + ticks = 0; 3.208 + } 3.209 +} 3.210 + 3.211 +ISR(USART0_RX_vect) 3.212 +{ 3.213 + char c = UDR0; 3.214 + 3.215 + if(c == '\r') { 3.216 + c = '\n'; 3.217 + } 3.218 + 3.219 + inbuf[in_wr] = c; 3.220 + in_wr = NEXT_IDX(in_wr); 3.221 +} 3.222 + 3.223 +/* USART Tx data register empty (can send more data) */ 3.224 +ISR(USART0_UDRE_vect) 3.225 +{ 3.226 + if(out_rd != out_wr) { 3.227 + UDR0 = outbuf[out_rd]; 3.228 + out_rd = NEXT_IDX(out_rd); 3.229 + } else { 3.230 + /* no more data to send for now, disable the interrupt */ 3.231 + UCSR0B &= ~(1 << UDRIE0); 3.232 + } 3.233 +}