working version
This commit is contained in:
parent
b47cfa680d
commit
2e14fe9090
395
main.c
395
main.c
@ -21,8 +21,6 @@
|
|||||||
#define F_CPU 8000000
|
#define F_CPU 8000000
|
||||||
#include <util/delay.h>
|
#include <util/delay.h>
|
||||||
|
|
||||||
#define USE_HEX 0
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* attiny2313
|
* attiny2313
|
||||||
* lfuse: 0xe4 (int rc osc, max startup time)
|
* lfuse: 0xe4 (int rc osc, max startup time)
|
||||||
@ -50,15 +48,65 @@
|
|||||||
#define nWRITE PORTD5
|
#define nWRITE PORTD5
|
||||||
#define nREAD PORTD6
|
#define nREAD PORTD6
|
||||||
|
|
||||||
#define PAGE_SIZE 64
|
|
||||||
|
|
||||||
#define BAUDRATE 115200
|
#define BAUDRATE 115200
|
||||||
|
|
||||||
#define UART_CALC_BAUDRATE(baudRate) (((uint32_t)F_CPU) / (((uint32_t)baudRate)*16) -1)
|
#define UART_CALC_BAUDRATE(baudRate) (((uint32_t)F_CPU) / (((uint32_t)baudRate)*16) -1)
|
||||||
|
|
||||||
#define NOP asm volatile ("nop")
|
#define NOP asm volatile ("nop")
|
||||||
|
|
||||||
static uint16_t g_address;
|
/* ************************************************************************* */
|
||||||
|
|
||||||
|
#define MSGTYPE_VERSION_REQ 0x01 /* no payload */
|
||||||
|
#define MSGTYPE_PAGESIZE_REQ 0x02 /* no payload */
|
||||||
|
#define MSGTYPE_CONFIG_REQ 0x03 /* eprom_type(1), pagesize(1), reset_polarity(1) */
|
||||||
|
#define MSGTYPE_PROGMODE_REQ 0x04 /* progmode(1) */
|
||||||
|
#define MSGTYPE_SETADDRESS_REQ 0x05 /* address(3) msb first */
|
||||||
|
#define MSGTYPE_WRITE_REQ 0x06 /* data(0-pagesize) */
|
||||||
|
#define MSGTYPE_READ_REQ 0x07 /* length(1) */
|
||||||
|
|
||||||
|
#define MSGTYPE_ERROR_RSP 0x80 /* error_code(1) */
|
||||||
|
#define MSGTYPE_VERSION_RSP 0x81 /* version(?) */
|
||||||
|
#define MSGTYPE_PAGESIZE_RSP 0x82 /* pagesize(1) */
|
||||||
|
#define MSGTYPE_CONFIG_RSP 0x83 /* no payload */
|
||||||
|
#define MSGTYPE_PROGMODE_RSP 0x84 /* no payload */
|
||||||
|
#define MSGTYPE_SETADDRESS_RSP 0x85 /* no payload */
|
||||||
|
#define MSGTYPE_WRITE_RSP 0x86 /* no payload */
|
||||||
|
#define MSGTYPE_READ_RSP 0x87 /* data(0-pagesize) */
|
||||||
|
|
||||||
|
#define SUCCESS 0x00
|
||||||
|
#define ERROR_UNKNOWN_COMMAND 0x01 /* unknown message type */
|
||||||
|
#define ERROR_NOT_SUPPORTED 0x02 /* command not supported */
|
||||||
|
#define ERROR_INVALID_MODE 0x03 /* invalid progmode */
|
||||||
|
#define ERROR_INVALID_PARAMETER 0x04 /* invalid parameter in request */
|
||||||
|
#define ERROR_INVALID_ADDRESS 0x05 /* write outside of configured region */
|
||||||
|
|
||||||
|
#define RESET_POLARITY_LOW 0x00 /* low active reset */
|
||||||
|
#define RESET_POLARITY_HIGH 0x01 /* high active reset */
|
||||||
|
|
||||||
|
#define EPROM_TYPE_2K 0x02 /* 2716 */
|
||||||
|
#define EPROM_TYPE_4K 0x04 /* 2732 */
|
||||||
|
#define EPROM_TYPE_8K 0x08 /* 2764 */
|
||||||
|
#define EPROM_TYPE_16K 0x10 /* 27128 */
|
||||||
|
#define EPROM_TYPE_32K 0x20 /* 27256 */
|
||||||
|
#define EPROM_TYPE_64K 0x40 /* 27512 */
|
||||||
|
#define EPROM_TYPE_128K 0x80 /* 27010 */
|
||||||
|
|
||||||
|
#define PROGMODE_DISABLED 0x00 /* target running, no write access to RAM */
|
||||||
|
#define PROGMODE_ENABLED 0x01 /* target reset, write access to RAM */
|
||||||
|
|
||||||
|
#define PAGESIZE_MAX 64
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
|
||||||
|
struct _globdata {
|
||||||
|
uint32_t address_max;
|
||||||
|
uint32_t address;
|
||||||
|
uint8_t progmode;
|
||||||
|
uint8_t pagesize;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t version_str[] = "e2prog v1.00";
|
||||||
|
static struct _globdata gdata = { 0 };
|
||||||
|
|
||||||
/* *************************************************************************
|
/* *************************************************************************
|
||||||
* send one byte to UART
|
* send one byte to UART
|
||||||
@ -80,71 +128,6 @@ static uint8_t ser_recv(void)
|
|||||||
} /* ser_recv */
|
} /* 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) */
|
|
||||||
|
|
||||||
|
|
||||||
/* *************************************************************************
|
/* *************************************************************************
|
||||||
*
|
*
|
||||||
* ************************************************************************* */
|
* ************************************************************************* */
|
||||||
@ -160,23 +143,19 @@ static void address_clear(void)
|
|||||||
NOP;
|
NOP;
|
||||||
PORTD &= ~(1<<REGCLK);
|
PORTD &= ~(1<<REGCLK);
|
||||||
|
|
||||||
g_address = 0;
|
gdata.address = 0;
|
||||||
} /* address_clear */
|
} /* address_clear */
|
||||||
|
|
||||||
|
|
||||||
/* *************************************************************************
|
/* *************************************************************************
|
||||||
* set address counter to value
|
* set address counter to value
|
||||||
* ************************************************************************* */
|
* ************************************************************************* */
|
||||||
static void address_set(void)
|
static void address_set(uint16_t address)
|
||||||
{
|
{
|
||||||
uint16_t count;
|
uint16_t count;
|
||||||
uint16_t address;
|
|
||||||
|
|
||||||
address = ser_recv_comm() << 8;
|
|
||||||
address |= ser_recv_comm();
|
|
||||||
|
|
||||||
/* address already higher then target */
|
/* address already higher then target */
|
||||||
if (g_address > address)
|
if (gdata.address > address)
|
||||||
{
|
{
|
||||||
/* reset address counter */
|
/* reset address counter */
|
||||||
PORTA &= ~(1<<nCNTRES);
|
PORTA &= ~(1<<nCNTRES);
|
||||||
@ -187,7 +166,7 @@ static void address_set(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
count = (address - g_address);
|
count = (address - gdata.address);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* increase address counter */
|
/* increase address counter */
|
||||||
@ -203,10 +182,7 @@ static void address_set(void)
|
|||||||
NOP;
|
NOP;
|
||||||
PORTD &= ~(1<<REGCLK);
|
PORTD &= ~(1<<REGCLK);
|
||||||
|
|
||||||
g_address = address;
|
gdata.address = address;
|
||||||
|
|
||||||
// ser_send_hex(address >> 8);
|
|
||||||
// ser_send_hex(address & 0xFF);
|
|
||||||
} /* address_set */
|
} /* address_set */
|
||||||
|
|
||||||
|
|
||||||
@ -225,25 +201,61 @@ static void address_inc(void)
|
|||||||
NOP;
|
NOP;
|
||||||
PORTD &= ~(1<<REGCLK);
|
PORTD &= ~(1<<REGCLK);
|
||||||
|
|
||||||
g_address++;
|
gdata.address++;
|
||||||
} /* address_inc */
|
} /* address_inc */
|
||||||
|
|
||||||
|
|
||||||
|
/* *************************************************************************
|
||||||
|
* configures max. address
|
||||||
|
* ************************************************************************* */
|
||||||
|
static uint8_t set_eprom_type(uint8_t type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case EPROM_TYPE_2K:
|
||||||
|
gdata.address_max = 0x0800;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EPROM_TYPE_4K:
|
||||||
|
gdata.address_max = 0x1000;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EPROM_TYPE_8K:
|
||||||
|
gdata.address_max = 0x2000;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EPROM_TYPE_16K:
|
||||||
|
gdata.address_max = 0x4000;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EPROM_TYPE_32K:
|
||||||
|
gdata.address_max = 0x8000;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EPROM_TYPE_64K:
|
||||||
|
gdata.address_max = 0x10000;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
|
} /* set_eprom_type */
|
||||||
|
|
||||||
|
|
||||||
/* *************************************************************************
|
/* *************************************************************************
|
||||||
* read data from eeprom
|
* read data from eeprom
|
||||||
* ************************************************************************* */
|
* ************************************************************************* */
|
||||||
static void data_read(void)
|
static void data_read(uint8_t length)
|
||||||
{
|
{
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
uint8_t data;
|
uint8_t data;
|
||||||
uint8_t count;
|
|
||||||
|
|
||||||
count = ser_recv_comm();
|
|
||||||
|
|
||||||
DDRB = 0x00;
|
DDRB = 0x00;
|
||||||
PORTB = 0x00;
|
PORTB = 0x00;
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
PORTD &= ~((1<<nCHIPSELECT) | (1<<nREAD));
|
PORTD &= ~((1<<nCHIPSELECT) | (1<<nREAD));
|
||||||
NOP;
|
NOP;
|
||||||
@ -251,8 +263,7 @@ static void data_read(void)
|
|||||||
PORTD |= (1<<nCHIPSELECT) | (1<<nREAD);
|
PORTD |= (1<<nCHIPSELECT) | (1<<nREAD);
|
||||||
|
|
||||||
address_inc();
|
address_inc();
|
||||||
|
ser_send(data);
|
||||||
ser_send_comm(data);
|
|
||||||
}
|
}
|
||||||
} /* data_read */
|
} /* data_read */
|
||||||
|
|
||||||
@ -280,27 +291,20 @@ static void data_poll(uint8_t value)
|
|||||||
/* *************************************************************************
|
/* *************************************************************************
|
||||||
* read data to eeprom
|
* read data to eeprom
|
||||||
* ************************************************************************* */
|
* ************************************************************************* */
|
||||||
static void data_write(void)
|
static void data_write(uint8_t length)
|
||||||
{
|
{
|
||||||
static uint8_t buffer[PAGE_SIZE];
|
static uint8_t buffer[PAGESIZE_MAX];
|
||||||
|
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
uint8_t count;
|
|
||||||
|
|
||||||
count = ser_recv_comm();
|
for (i = 0; i < length; i++)
|
||||||
if (count > PAGE_SIZE)
|
|
||||||
{
|
{
|
||||||
count = PAGE_SIZE;
|
buffer[i] = ser_recv();
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
buffer[i] = ser_recv_comm();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DDRB = 0xFF;
|
DDRB = 0xFF;
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
PORTB = buffer[i];
|
PORTB = buffer[i];
|
||||||
|
|
||||||
@ -309,7 +313,7 @@ static void data_write(void)
|
|||||||
PORTD |= (1<<nCHIPSELECT) | (1<<nWRITE);
|
PORTD |= (1<<nCHIPSELECT) | (1<<nWRITE);
|
||||||
|
|
||||||
/* last address of page -> start polling */
|
/* last address of page -> start polling */
|
||||||
if ((g_address & (sizeof(buffer) -1)) == (sizeof(buffer) -1))
|
if ((gdata.address & (gdata.pagesize -1)) == (gdata.pagesize -1))
|
||||||
{
|
{
|
||||||
data_poll(buffer[i]);
|
data_poll(buffer[i]);
|
||||||
DDRB = 0xFF;
|
DDRB = 0xFF;
|
||||||
@ -318,6 +322,8 @@ static void data_write(void)
|
|||||||
address_inc();
|
address_inc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data_poll(buffer[length -1]);
|
||||||
|
|
||||||
DDRB = 0x00;
|
DDRB = 0x00;
|
||||||
PORTB = 0x00;
|
PORTB = 0x00;
|
||||||
} /* data_write */
|
} /* data_write */
|
||||||
@ -351,37 +357,180 @@ int main(void)
|
|||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
switch (ser_recv())
|
uint8_t msgtype = ser_recv();
|
||||||
|
uint8_t length = ser_recv();
|
||||||
|
uint8_t error_code = ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
switch (msgtype)
|
||||||
{
|
{
|
||||||
case 'a':
|
case MSGTYPE_VERSION_REQ:
|
||||||
address_set();
|
if (length == 0x00)
|
||||||
ser_send('\r');
|
{
|
||||||
ser_send('\n');
|
ser_send(MSGTYPE_VERSION_RSP);
|
||||||
|
ser_send(sizeof(version_str) -1);
|
||||||
|
|
||||||
|
const uint8_t * p_data = version_str;
|
||||||
|
while (*p_data)
|
||||||
|
{
|
||||||
|
ser_send(*p_data++);
|
||||||
|
}
|
||||||
|
|
||||||
|
error_code = SUCCESS;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'b':
|
case MSGTYPE_PAGESIZE_REQ:
|
||||||
ser_send_comm(PAGE_SIZE);
|
if (length == 0x00)
|
||||||
ser_send('\r');
|
{
|
||||||
ser_send('\n');
|
ser_send(MSGTYPE_PAGESIZE_RSP);
|
||||||
|
ser_send(0x01);
|
||||||
|
ser_send(PAGESIZE_MAX);
|
||||||
|
|
||||||
|
error_code = SUCCESS;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'r':
|
case MSGTYPE_CONFIG_REQ:
|
||||||
data_read();
|
if (length == 0x03)
|
||||||
ser_send('\r');
|
{
|
||||||
ser_send('\n');
|
uint8_t eprom_type = ser_recv();
|
||||||
|
uint8_t pagesize = ser_recv();
|
||||||
|
|
||||||
|
/* reset polarity not used on this target */
|
||||||
|
ser_recv();
|
||||||
|
|
||||||
|
if (gdata.progmode == PROGMODE_ENABLED)
|
||||||
|
{
|
||||||
|
error_code = ERROR_INVALID_MODE;
|
||||||
|
}
|
||||||
|
else if ((pagesize <= PAGESIZE_MAX) &&
|
||||||
|
(set_eprom_type(eprom_type) == SUCCESS)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
gdata.pagesize = pagesize;
|
||||||
|
|
||||||
|
ser_send(MSGTYPE_CONFIG_RSP);
|
||||||
|
ser_send(0x00);
|
||||||
|
error_code = SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'w':
|
case MSGTYPE_PROGMODE_REQ:
|
||||||
data_write();
|
if (length == 0x01)
|
||||||
ser_send('\r');
|
{
|
||||||
ser_send('\n');
|
uint8_t progmode = ser_recv();
|
||||||
|
|
||||||
|
if (progmode <= PROGMODE_ENABLED)
|
||||||
|
{
|
||||||
|
gdata.progmode = progmode;
|
||||||
|
|
||||||
|
ser_send(MSGTYPE_PROGMODE_RSP);
|
||||||
|
ser_send(0x00);
|
||||||
|
error_code = SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSGTYPE_SETADDRESS_REQ:
|
||||||
|
if (length == 0x03)
|
||||||
|
{
|
||||||
|
uint32_t address;
|
||||||
|
|
||||||
|
address = ser_recv();
|
||||||
|
address = (address<<8) | ser_recv();
|
||||||
|
address = (address<<8) | ser_recv();
|
||||||
|
|
||||||
|
if (address < gdata.address_max)
|
||||||
|
{
|
||||||
|
if (gdata.progmode == PROGMODE_DISABLED)
|
||||||
|
{
|
||||||
|
error_code = ERROR_INVALID_MODE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
address_set(address);
|
||||||
|
|
||||||
|
ser_send(MSGTYPE_SETADDRESS_RSP);
|
||||||
|
ser_send(0x00);
|
||||||
|
error_code = SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSGTYPE_WRITE_REQ:
|
||||||
|
if ((length > 0) &&
|
||||||
|
(length <= gdata.pagesize)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if ((gdata.address >= gdata.address_max) ||
|
||||||
|
((gdata.address + length) > gdata.address_max)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
error_code = ERROR_INVALID_ADDRESS;
|
||||||
|
}
|
||||||
|
else if (gdata.progmode == PROGMODE_DISABLED)
|
||||||
|
{
|
||||||
|
error_code = ERROR_INVALID_MODE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data_write(length);
|
||||||
|
|
||||||
|
ser_send(MSGTYPE_WRITE_RSP);
|
||||||
|
ser_send(0x00);
|
||||||
|
error_code = SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MSGTYPE_READ_REQ:
|
||||||
|
if (length == 0x01)
|
||||||
|
{
|
||||||
|
uint8_t size = ser_recv();
|
||||||
|
|
||||||
|
if (size <= PAGESIZE_MAX)
|
||||||
|
{
|
||||||
|
if ((gdata.address >= gdata.address_max) ||
|
||||||
|
((gdata.address + size) > gdata.address_max)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
error_code = ERROR_INVALID_ADDRESS;
|
||||||
|
}
|
||||||
|
else if (gdata.progmode == PROGMODE_DISABLED)
|
||||||
|
{
|
||||||
|
error_code = ERROR_INVALID_MODE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ser_send(MSGTYPE_READ_RSP);
|
||||||
|
ser_send(size);
|
||||||
|
|
||||||
|
data_read(size);
|
||||||
|
|
||||||
|
error_code = SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ser_send('?');
|
error_code = ERROR_UNKNOWN_COMMAND;
|
||||||
ser_send('\r');
|
|
||||||
ser_send('\n');
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (error_code != SUCCESS)
|
||||||
|
{
|
||||||
|
/* read remaining request */
|
||||||
|
while (length--)
|
||||||
|
{
|
||||||
|
(void)ser_recv();
|
||||||
|
}
|
||||||
|
|
||||||
|
ser_send(MSGTYPE_ERROR_RSP);
|
||||||
|
ser_send(0x01);
|
||||||
|
ser_send(error_code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} /* main */
|
} /* main */
|
||||||
|
Loading…
Reference in New Issue
Block a user