initial commit
This commit is contained in:
commit
9e69670da0
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
*.o
|
||||||
|
*.elf
|
||||||
|
*.bin
|
||||||
|
*.hex
|
||||||
|
*.lst
|
||||||
|
*.map
|
56
Makefile
Normal file
56
Makefile
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
PRG = epromsim
|
||||||
|
OBJ = main.o
|
||||||
|
MCU_TARGET = attiny2313
|
||||||
|
OPTIMIZE = -Os
|
||||||
|
|
||||||
|
#AVRDUDE_PROG = -c avr910 -b 115200 -P /dev/ispprog
|
||||||
|
AVRDUDE_PROG = -c dragon_isp -P usb
|
||||||
|
AVRDUDE_MCU = attiny2313
|
||||||
|
|
||||||
|
DEFS =
|
||||||
|
LIBS =
|
||||||
|
|
||||||
|
# Override is only needed by avr-lib build system.
|
||||||
|
override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS)
|
||||||
|
override LDFLAGS = -Wl,-Map,$(PRG).map
|
||||||
|
|
||||||
|
CC = avr-gcc
|
||||||
|
OBJCOPY = avr-objcopy
|
||||||
|
OBJDUMP = avr-objdump
|
||||||
|
SIZE = avr-size
|
||||||
|
|
||||||
|
all: $(PRG).elf lst text
|
||||||
|
$(SIZE) -x -A $(PRG).elf
|
||||||
|
|
||||||
|
$(PRG).elf: $(OBJ)
|
||||||
|
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||||
|
|
||||||
|
%.o: %.c $(MAKEFILE_LIST)
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf *.o $(PRG).lst $(PRG).map $(PRG).elf $(PRG).hex $(PRG).bin
|
||||||
|
|
||||||
|
lst: $(PRG).lst
|
||||||
|
|
||||||
|
%.lst: %.elf
|
||||||
|
$(OBJDUMP) -h -S $< > $@
|
||||||
|
|
||||||
|
text: hex bin
|
||||||
|
|
||||||
|
hex: $(PRG).hex
|
||||||
|
bin: $(PRG).bin
|
||||||
|
|
||||||
|
%.hex: %.elf
|
||||||
|
$(OBJCOPY) -j .text -j .data -O ihex $< $@
|
||||||
|
|
||||||
|
%.bin: %.elf
|
||||||
|
$(OBJCOPY) -j .text -j .data -O binary $< $@
|
||||||
|
|
||||||
|
install: text
|
||||||
|
avrdude $(AVRDUDE_PROG) -p $(AVRDUDE_MCU) -V -U flash:w:$(PRG).hex
|
||||||
|
|
||||||
|
fuses:
|
||||||
|
avrdude $(AVRDUDE_PROG) -p $(AVRDUDE_MCU) -U efuse:w:0xff:m
|
||||||
|
avrdude $(AVRDUDE_PROG) -p $(AVRDUDE_MCU) -U hfuse:w:0xdb:m
|
||||||
|
avrdude $(AVRDUDE_PROG) -p $(AVRDUDE_MCU) -U lfuse:w:0xff:m
|
368
main.c
Normal file
368
main.c
Normal file
@ -0,0 +1,368 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 04/2013 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>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
|
#define F_CPU 11059200
|
||||||
|
#include <util/delay.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* attiny2313
|
||||||
|
* lfuse: 0xff (ext. crystal, slow rising power, max startup time)
|
||||||
|
* hfuse: 0xdb (2.7V BOD)
|
||||||
|
* efuse: 0xff (self Prog enabled)
|
||||||
|
*
|
||||||
|
* PB0 -> NC
|
||||||
|
* PB1 -> reset-out
|
||||||
|
* PB2 -> /WR SRAM
|
||||||
|
* PB3 -> SRCK (shift register clock)
|
||||||
|
* PB4 -> SER (shift register input)
|
||||||
|
* PB5 -> CCK (counter clock)
|
||||||
|
* PB6 -> RCK (counter and shift register store clock)
|
||||||
|
* PB7 -> /OE (output enable counter, shift register, reset-out, A16)
|
||||||
|
* PD0 <- RXD
|
||||||
|
* PD1 -> TXD
|
||||||
|
* PD2 <- /PowerFail
|
||||||
|
* PD3 -> A16
|
||||||
|
* PD4 -> /LED_GN
|
||||||
|
* PD5 -> /LED_RT
|
||||||
|
* PD6 -> /OE (output enable RAM and address buffer, counter clear)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RESET_OUT PORTB1
|
||||||
|
#define nRAM_WR PORTB2
|
||||||
|
#define SREG_CLK PORTB3
|
||||||
|
#define SREG_DAT PORTB4
|
||||||
|
#define CNT_CLK PORTB5
|
||||||
|
#define REG_STORE PORTB6
|
||||||
|
#define nEMU_EN PORTB7
|
||||||
|
|
||||||
|
#define RXD PORTD0
|
||||||
|
#define TXD PORTD1
|
||||||
|
#define nPOWERFAIL PORTD2
|
||||||
|
#define EMU_A16 PORTD3
|
||||||
|
#define nLED_GN PORTD4
|
||||||
|
#define nLED_RT PORTD5
|
||||||
|
#define nTARGET_EN PORTD6
|
||||||
|
|
||||||
|
#define BAUDRATE 115200
|
||||||
|
|
||||||
|
#define UART_CALC_BAUDRATE(baudRate) (((uint32_t)F_CPU) / (((uint32_t)baudRate)*16) -1)
|
||||||
|
|
||||||
|
struct _globdata {
|
||||||
|
uint8_t address_mask;
|
||||||
|
uint8_t reset_polarity;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct _globdata gdata = { 0 };
|
||||||
|
|
||||||
|
|
||||||
|
/* *************************************************************************
|
||||||
|
* 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 */
|
||||||
|
|
||||||
|
|
||||||
|
/* *************************************************************************
|
||||||
|
* shift one byte out to register (LSB first)
|
||||||
|
* ************************************************************************* */
|
||||||
|
static void shift_data(uint8_t data)
|
||||||
|
{
|
||||||
|
uint8_t mask;
|
||||||
|
|
||||||
|
for (mask = 0x01; mask != 0; mask <<= 1) {
|
||||||
|
if (data & mask) {
|
||||||
|
PORTB |= (1<<SREG_DAT);
|
||||||
|
} else {
|
||||||
|
PORTB &= ~(1<<SREG_DAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* positive edge clocks in data */
|
||||||
|
PORTB |= (1<<SREG_CLK);
|
||||||
|
PORTB &= ~(1<<SREG_CLK);
|
||||||
|
}
|
||||||
|
} /* shift_data */
|
||||||
|
|
||||||
|
|
||||||
|
/* *************************************************************************
|
||||||
|
* store pulse for register and counter
|
||||||
|
* ************************************************************************* */
|
||||||
|
static void store_pulse(void)
|
||||||
|
{
|
||||||
|
/* positive edge transfers data to output buffer */
|
||||||
|
PORTB |= (1<<REG_STORE);
|
||||||
|
PORTB &= ~(1<<REG_STORE);
|
||||||
|
} /* store_pulse */
|
||||||
|
|
||||||
|
|
||||||
|
/* *************************************************************************
|
||||||
|
* write pulse for SRAM and increment counter
|
||||||
|
* ************************************************************************* */
|
||||||
|
static void write_inc_pulse(void)
|
||||||
|
{
|
||||||
|
/* positive edge clocks in data */
|
||||||
|
PORTB &= ~(1<<nRAM_WR);
|
||||||
|
PORTB |= (1<<nRAM_WR);
|
||||||
|
|
||||||
|
/* positive edge increments counter */
|
||||||
|
PORTB |= (1<<CNT_CLK);
|
||||||
|
PORTB &= ~(1<<CNT_CLK);
|
||||||
|
} /* write_inc_pulse */
|
||||||
|
|
||||||
|
|
||||||
|
/* *************************************************************************
|
||||||
|
* switch access to RAM between emulator and target
|
||||||
|
* ************************************************************************* */
|
||||||
|
static void do_reset(uint8_t enable)
|
||||||
|
{
|
||||||
|
if (enable) {
|
||||||
|
/* switch RAM access to EMU */
|
||||||
|
PORTD |= (1<<nTARGET_EN);
|
||||||
|
PORTD &= ~(1<<nLED_RT);
|
||||||
|
PORTB &= ~(1<<nEMU_EN);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* set eprom address line mask */
|
||||||
|
shift_data(gdata.address_mask);
|
||||||
|
shift_data(0x00);
|
||||||
|
store_pulse();
|
||||||
|
|
||||||
|
/* switch RAM access to TARGET */
|
||||||
|
PORTB |= (1<<nEMU_EN);
|
||||||
|
PORTD &= ~(1<<nTARGET_EN);
|
||||||
|
PORTD |= (1<<nLED_RT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set RESET_OUT */
|
||||||
|
if (enable ^ gdata.reset_polarity) {
|
||||||
|
PORTB &= ~(1<<RESET_OUT);
|
||||||
|
} else {
|
||||||
|
PORTB |= (1<<RESET_OUT);
|
||||||
|
}
|
||||||
|
} /* do_reset */
|
||||||
|
|
||||||
|
|
||||||
|
/* *************************************************************************
|
||||||
|
* configures number of addresslines and loads data from UART into RAM
|
||||||
|
* ************************************************************************* */
|
||||||
|
static void do_load(uint8_t type, uint32_t length)
|
||||||
|
{
|
||||||
|
uint32_t size;
|
||||||
|
switch (type) {
|
||||||
|
case 0x02: /* 2716 - 2kB */
|
||||||
|
size = 0x0800;
|
||||||
|
gdata.address_mask = 0x00;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x04: /* 2732 - 4kB */
|
||||||
|
size = 0x1000;
|
||||||
|
gdata.address_mask = 0x80;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x08: /* 2764 - 8kB */
|
||||||
|
size = 0x2000;
|
||||||
|
gdata.address_mask = 0xC0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x10: /* 27128 - 16kB */
|
||||||
|
size = 0x4000;
|
||||||
|
gdata.address_mask = 0xE0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x20: /* 27256 - 32kB */
|
||||||
|
size = 0x8000;
|
||||||
|
gdata.address_mask = 0xF0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x40: /* 27512 - 64kB */
|
||||||
|
size = 0x10000;
|
||||||
|
gdata.address_mask = 0xF8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
case 0x80: /* 27010 - 128kB */
|
||||||
|
size = 0x20000;
|
||||||
|
gdata.address_mask = 0xFC;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
do_reset(1);
|
||||||
|
|
||||||
|
uint32_t i;
|
||||||
|
uint8_t data;
|
||||||
|
for (i = 0; i < size; i++) {
|
||||||
|
if (i > 0xFFFF) {
|
||||||
|
PORTD |= (1<<EMU_A16);
|
||||||
|
} else {
|
||||||
|
PORTD &= ~(1<<EMU_A16);
|
||||||
|
}
|
||||||
|
|
||||||
|
data = (i < length) ? ser_recv() : 0xFF;
|
||||||
|
shift_data(data);
|
||||||
|
store_pulse();
|
||||||
|
write_inc_pulse();
|
||||||
|
}
|
||||||
|
|
||||||
|
do_reset(0);
|
||||||
|
} /* do_load */
|
||||||
|
|
||||||
|
|
||||||
|
/* *************************************************************************
|
||||||
|
* clears whole RAM (writes 0xFF)
|
||||||
|
* ************************************************************************* */
|
||||||
|
static void do_clear(void)
|
||||||
|
{
|
||||||
|
do_reset(1);
|
||||||
|
|
||||||
|
shift_data(0xFF);
|
||||||
|
|
||||||
|
uint16_t i = 0xFFFF;
|
||||||
|
|
||||||
|
PORTD &= ~(1<<EMU_A16);
|
||||||
|
do {
|
||||||
|
store_pulse();
|
||||||
|
write_inc_pulse();
|
||||||
|
} while (i--);
|
||||||
|
|
||||||
|
PORTD |= (1<<EMU_A16);
|
||||||
|
do {
|
||||||
|
store_pulse();
|
||||||
|
write_inc_pulse();
|
||||||
|
} while (i--);
|
||||||
|
|
||||||
|
do_reset(0);
|
||||||
|
} /* do_clear */
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* Powerfail / Wakeup */
|
||||||
|
ISR(INT0_vect)
|
||||||
|
{
|
||||||
|
if (1) {
|
||||||
|
/*
|
||||||
|
* Power Fail:
|
||||||
|
* - enable RESET_OUT
|
||||||
|
* - disable nTARGET_EN
|
||||||
|
* - enable rising edge INT0 (nPOWERFAIL)
|
||||||
|
* - disable pullups
|
||||||
|
* - put MCU in standby
|
||||||
|
*/
|
||||||
|
do_reset(1);
|
||||||
|
|
||||||
|
/* disable green LED */
|
||||||
|
PORTD |= (1<<nLED_GN);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Power Restore:
|
||||||
|
* - enable pullups
|
||||||
|
* - enable falling edge INT0 (nPOWERFAIL)
|
||||||
|
* - enable nTARGET_EN again
|
||||||
|
* - disable RESET_OUT
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* enable green LED */
|
||||||
|
PORTD &= ~(1<<nLED_GN);
|
||||||
|
|
||||||
|
do_reset(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
int main(void) __attribute__ ((noreturn));
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
DDRB = 0xFF;
|
||||||
|
PORTB = (1<<nRAM_WR) | (1<<nEMU_EN);
|
||||||
|
|
||||||
|
DDRD = ~((1<<RXD) | (1<<nPOWERFAIL));
|
||||||
|
PORTD = (1<<RXD) | (1<<nPOWERFAIL) | (1<<nLED_GN) | (1<<nLED_RT) | (1<<nTARGET_EN);
|
||||||
|
|
||||||
|
/* enable UART 115200,8n1 */
|
||||||
|
UBRRH = (UART_CALC_BAUDRATE(BAUDRATE)>>8) & 0xFF;
|
||||||
|
UBRRL = (UART_CALC_BAUDRATE(BAUDRATE) & 0xFF);
|
||||||
|
UCSRC = (1<<UCSZ1) | (1<<UCSZ0);
|
||||||
|
UCSRB = (1<<RXEN) | (1<<TXEN);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* powerfail: detect falling edge on INT0 */
|
||||||
|
MCUCR = (1<<ISC01);
|
||||||
|
GIMSK = (1<<INT0);
|
||||||
|
sei();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* enable LED and reset Counter */
|
||||||
|
PORTD &= ~((1<<nLED_GN) | (1<<nTARGET_EN));
|
||||||
|
|
||||||
|
/* init RAM */
|
||||||
|
gdata.address_mask = 0x3F;
|
||||||
|
do_clear();
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
uint8_t cmd = ser_recv();
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case 'p': /* low active reset */
|
||||||
|
gdata.reset_polarity = 0;
|
||||||
|
ser_send('\n');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'P': /* high active reset */
|
||||||
|
gdata.reset_polarity = 1;
|
||||||
|
ser_send('\n');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'r': /* reset pulse */
|
||||||
|
do_reset(1);
|
||||||
|
_delay_ms(10);
|
||||||
|
do_reset(0);
|
||||||
|
ser_send('\n');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'l': /* load eprom content */
|
||||||
|
{
|
||||||
|
uint8_t type = ser_recv();
|
||||||
|
uint32_t length = (uint32_t)ser_recv() << 16;
|
||||||
|
length |= ser_recv() << 8;
|
||||||
|
length |= ser_recv();
|
||||||
|
|
||||||
|
do_load(type, length);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ser_send('?');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user