initial commit

This commit is contained in:
Olaf Rempel 2017-05-29 21:06:08 +02:00
commit b47cfa680d
3 changed files with 442 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
*.o
*.elf
*.bin
*.hex
*.lst
*.lss
*.map

48
Makefile Normal file
View File

@ -0,0 +1,48 @@
CC := avr-gcc
LD := avr-ld
OBJCOPY := avr-objcopy
OBJDUMP := avr-objdump
SIZE := avr-size
TARGET = e2promprog
SOURCE = $(wildcard *.c)
MCU=attiny2313
AVRDUDE_MCU=attiny2313
AVRDUDE_FUSES=lfuse:w:0xe4:m hfuse:w:0xdf:m efuse:w:0xff:m
AVRDUDE_PROG := -c avr910 -b 115200 -P /dev/ispprog
#AVRDUDE_PROG := -c dragon_isp -P usb
# ---------------------------------------------------------------------------
CFLAGS = -pipe -g -Os -mmcu=$(MCU) -Wall
CFLAGS += -fdata-sections -ffunction-sections
CFLAGS += -Wa,-adhlns=$(*F).lst
LDFLAGS = -Wl,-Map,$(@:.elf=.map),--cref
LDFLAGS += -Wl,--relax,--gc-sections
# ---------------------------------------------------------------------------
$(TARGET): $(TARGET).elf
@$(SIZE) -B -x --mcu=$(MCU) $<
$(TARGET).elf: $(SOURCE:.c=.o)
@echo " Linking file: $@"
@$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ 2> /dev/null
@$(OBJDUMP) -h -S $@ > $(@:.elf=.lss)
@$(OBJCOPY) -j .text -j .data -O ihex $@ $(@:.elf=.hex)
@$(OBJCOPY) -j .text -j .data -O binary $@ $(@:.elf=.bin)
%.o: %.c $(MAKEFILE_LIST)
@echo " Building file: $<"
@$(CC) $(CFLAGS) -o $@ -c $<
clean:
rm -rf $(SOURCE:.c=.o) $(SOURCE:.c=.lst) $(addprefix $(TARGET), .elf .map .lss .hex .bin)
install: $(TARGET).elf
avrdude $(AVRDUDE_PROG) -p $(AVRDUDE_MCU) -U flash:w:$(<:.elf=.hex)
fuses:
avrdude $(AVRDUDE_PROG) -p $(AVRDUDE_MCU) $(patsubst %,-U %, $(AVRDUDE_FUSES))

387
main.c Normal file
View File

@ -0,0 +1,387 @@
/***************************************************************************
* Copyright (C) 02/2017 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; version 2 of the License, *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <avr/io.h>
#define F_CPU 8000000
#include <util/delay.h>
#define USE_HEX 0
/*
* attiny2313
* lfuse: 0xe4 (int rc osc, max startup time)
* hfuse: 0xdf (no BOD)
* efuse: 0xff (no self programming)
*
* PA0 -> HC590 /MRC (Counter Reset)
* PB0:7 <-> D0:7
* PD0 <- RXD
* PD1 -> TXD
* PD2 -> HC590 CPC (Counter Clock)
* PD3 -> HC590 CPR (Register Clock)
* PD4 -> EEPROM /CS
* PD5 -> EEPROM /WR
* PD6 -> EEPROM /OE
*/
#define nCNTRES PORTA0
#define RXD PORTD0
#define TXD PORTD1
#define CNTCLK PORTD2
#define REGCLK PORTD3
#define nCHIPSELECT PORTD4
#define nWRITE PORTD5
#define nREAD PORTD6
#define PAGE_SIZE 64
#define BAUDRATE 115200
#define UART_CALC_BAUDRATE(baudRate) (((uint32_t)F_CPU) / (((uint32_t)baudRate)*16) -1)
#define NOP asm volatile ("nop")
static uint16_t g_address;
/* *************************************************************************
* send one byte to UART
* ************************************************************************* */
static void ser_send(uint8_t data)
{
loop_until_bit_is_set(UCSRA, UDRIE);
UDR = data;
} /* ser_send */
/* *************************************************************************
* receive one byte from UART
* ************************************************************************* */
static uint8_t ser_recv(void)
{
loop_until_bit_is_set(UCSRA, RXC);
return UDR;
} /* ser_recv */
#if (USE_HEX)
/* *************************************************************************
*
* ************************************************************************* */
static void ser_send_hexnibble(uint8_t value)
{
value += (value < 0x0A) ? '0' : ('A' - 0x0A);
ser_send(value);
} /* ser_send_hexnibble */
/* *************************************************************************
*
* ************************************************************************* */
static void ser_send_hex(uint8_t value)
{
ser_send_hexnibble(value >> 4);
ser_send_hexnibble(value & 0x0F);
} /* ser_send_hex */
/* *************************************************************************
*
* ************************************************************************* */
static uint8_t ascii2hexnibble(uint8_t value)
{
if (value >= '0' && value <= '9')
{
return (value - '0');
}
else
{
value &= ~(0x20);
if (value >= 'A' && value <= 'F')
{
return (value - 'A' + 0x0A);
}
}
return 0;
} /* ascii2hexnibble */
/* *************************************************************************
*
* ************************************************************************* */
static uint8_t ser_recv_hex(void)
{
uint8_t result;
result = ascii2hexnibble(ser_recv()) << 4;
result |= ascii2hexnibble(ser_recv());
return result;
} /* ser_recv_hex */
#define ser_send_comm(x) ser_send_hex(x)
#define ser_recv_comm() ser_recv_hex()
#else
#define ser_send_comm(x) ser_send(x)
#define ser_recv_comm() ser_recv()
#endif /* (USE_HEX) */
/* *************************************************************************
*
* ************************************************************************* */
static void address_clear(void)
{
/* reset address counter */
PORTA &= ~(1<<nCNTRES);
NOP;
PORTA |= (1<<nCNTRES);
/* clock address into register */
PORTD |= (1<<REGCLK);
NOP;
PORTD &= ~(1<<REGCLK);
g_address = 0;
} /* address_clear */
/* *************************************************************************
* set address counter to value
* ************************************************************************* */
static void address_set(void)
{
uint16_t count;
uint16_t address;
address = ser_recv_comm() << 8;
address |= ser_recv_comm();
/* address already higher then target */
if (g_address > address)
{
/* reset address counter */
PORTA &= ~(1<<nCNTRES);
NOP;
PORTA |= (1<<nCNTRES);
count = address;
}
else
{
count = (address - g_address);
}
/* increase address counter */
while (count--)
{
PORTD |= (1<<CNTCLK);
NOP;
PORTD &= ~(1<<CNTCLK);
}
/* clock address into register */
PORTD |= (1<<REGCLK);
NOP;
PORTD &= ~(1<<REGCLK);
g_address = address;
// ser_send_hex(address >> 8);
// ser_send_hex(address & 0xFF);
} /* address_set */
/* *************************************************************************
* increase address by one
* ************************************************************************* */
static void address_inc(void)
{
/* increase address counter */
PORTD |= (1<<CNTCLK);
NOP;
PORTD &= ~(1<<CNTCLK);
/* clock address into register */
PORTD |= (1<<REGCLK);
NOP;
PORTD &= ~(1<<REGCLK);
g_address++;
} /* address_inc */
/* *************************************************************************
* read data from eeprom
* ************************************************************************* */
static void data_read(void)
{
uint8_t i;
uint8_t data;
uint8_t count;
count = ser_recv_comm();
DDRB = 0x00;
PORTB = 0x00;
for (i = 0; i < count; i++)
{
PORTD &= ~((1<<nCHIPSELECT) | (1<<nREAD));
NOP;
data = PINB;
PORTD |= (1<<nCHIPSELECT) | (1<<nREAD);
address_inc();
ser_send_comm(data);
}
} /* data_read */
/* *************************************************************************
*
* ************************************************************************* */
static void data_poll(uint8_t value)
{
uint16_t retry = 2000;
uint8_t data;
DDRB = 0x00;
PORTB = 0x00;
do {
PORTD &= ~((1<<nCHIPSELECT) | (1<<nREAD));
NOP;
data = PINB;
PORTD |= (1<<nCHIPSELECT) | (1<<nREAD);
} while (retry-- && (data != value));
} /* data_poll */
/* *************************************************************************
* read data to eeprom
* ************************************************************************* */
static void data_write(void)
{
static uint8_t buffer[PAGE_SIZE];
uint8_t i;
uint8_t count;
count = ser_recv_comm();
if (count > PAGE_SIZE)
{
count = PAGE_SIZE;
}
for (i = 0; i < count; i++)
{
buffer[i] = ser_recv_comm();
}
DDRB = 0xFF;
for (i = 0; i < count; i++)
{
PORTB = buffer[i];
PORTD &= ~((1<<nCHIPSELECT) | (1<<nWRITE));
NOP;
PORTD |= (1<<nCHIPSELECT) | (1<<nWRITE);
/* last address of page -> start polling */
if ((g_address & (sizeof(buffer) -1)) == (sizeof(buffer) -1))
{
data_poll(buffer[i]);
DDRB = 0xFF;
}
address_inc();
}
DDRB = 0x00;
PORTB = 0x00;
} /* data_write */
/* *************************************************************************
*
* ************************************************************************* */
int main(void) __attribute__ ((noreturn));
int main(void)
{
PORTA = (1<<nCNTRES);
DDRA = (1<<nCNTRES);
PORTB = 0x00;
DDRB = 0x00;
PORTD = (1<<RXD) | (1<<TXD) | (1<<nCHIPSELECT) | (1<<nWRITE) | (1<<nREAD);
DDRD = ~(1<<RXD);
/* increase rc osc frequency to reach 115200 baud */
OSCCAL = 0xCC;
/* enable UART 8n1 */
UBRRH = (UART_CALC_BAUDRATE(BAUDRATE)>>8) & 0xFF;
UBRRL = (UART_CALC_BAUDRATE(BAUDRATE) & 0xFF);
UCSRC = (1<<UCSZ1) | (1<<UCSZ0);
UCSRB = (1<<RXEN) | (1<<TXEN);
address_clear();
while (1)
{
switch (ser_recv())
{
case 'a':
address_set();
ser_send('\r');
ser_send('\n');
break;
case 'b':
ser_send_comm(PAGE_SIZE);
ser_send('\r');
ser_send('\n');
break;
case 'r':
data_read();
ser_send('\r');
ser_send('\n');
break;
case 'w':
data_write();
ser_send('\r');
ser_send('\n');
break;
default:
ser_send('?');
ser_send('\r');
ser_send('\n');
break;
}
}
} /* main */