initial commit
This commit is contained in:
commit
b47cfa680d
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
*.o
|
||||||
|
*.elf
|
||||||
|
*.bin
|
||||||
|
*.hex
|
||||||
|
*.lst
|
||||||
|
*.lss
|
||||||
|
*.map
|
48
Makefile
Normal file
48
Makefile
Normal 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
387
main.c
Normal 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 */
|
Loading…
Reference in New Issue
Block a user