rewrite
This commit is contained in:
parent
e1c00dc403
commit
9205611c5a
2
Makefile
2
Makefile
@ -48,4 +48,4 @@ bin: $(PRG).bin
|
|||||||
|
|
||||||
install: text
|
install: text
|
||||||
# uisp -dprog=stk200 --erase --upload if=$(PRG).hex --verify
|
# uisp -dprog=stk200 --erase --upload if=$(PRG).hex --verify
|
||||||
avrdude -p m16 -c butterfly -b 19200 -U flash:w:$(PRG).hex
|
avrdude -p m16 -c butterfly -b 19200 -P /dev/ttyUSB0 -U flash:w:$(PRG).hex
|
||||||
|
621
ispprog.c
621
ispprog.c
@ -1,59 +1,129 @@
|
|||||||
/*
|
/***************************************************************************
|
||||||
* C based avr910 / avr109 ISP Adapter
|
* C based avr910 / avr109 ISP Adapter *
|
||||||
*
|
* *
|
||||||
* (c) 2006-2008 by Olaf Rempel
|
* Copyright (C) 2006 - 20011 by Olaf Rempel *
|
||||||
* <razzor at kopf minus tisch dot de>
|
* razzor AT kopf MINUS tisch DOT de *
|
||||||
*
|
* *
|
||||||
* using ATmega16 @7.3728MHz:
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
* PB1 = /Reset (to target)
|
* it under the terms of the GNU General Public License as published by *
|
||||||
* PB3 = /LED
|
* the Free Software Foundation; version 2 of the License, *
|
||||||
* PB5 = MOSI (to target)
|
* *
|
||||||
* PB6 = MISO (to target)
|
* This program is distributed in the hope that it will be useful, *
|
||||||
* PB7 = SCK (to target)
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
* PD3 = reset-in
|
* 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/io.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* using ATmega16 @7.3728MHz:
|
||||||
|
* Fuse H: 0xDA (512 words bootloader, jtag disabled)
|
||||||
|
* Fuse L: 0xFF (ext. Crystal)
|
||||||
|
*/
|
||||||
|
|
||||||
#define F_CPU 7372800
|
#define F_CPU 7372800
|
||||||
#define BAUDRATE 115200
|
#define BAUDRATE 115200
|
||||||
|
#define TIMER_RELOAD (0xFF - 72) /* 10ms @7.3728MHz */
|
||||||
|
|
||||||
/* SPI Clock: F_CPU /4 (1.8432MHz) or /128 (57.6kHz) */
|
#define ISP_RESET PORTB1 /* to target */
|
||||||
#define SPI_MODE ((1<<SPE) | (1<<MSTR))
|
#define ISP_LED PORTB3 /* low active */
|
||||||
//#define SPI_MODE ((1<<SPE) | (1<<MSTR) | (1<<SPR1) | (1<<SPR0))
|
#define ISP_MOSI PORTB5 /* to target */
|
||||||
|
#define ISP_MISO PORTB6 /* to target */
|
||||||
#define ISP_RESET PORTB1
|
#define ISP_SCK PORTB7 /* to target */
|
||||||
#define ISP_LED PORTB3
|
#define RESET_IN PORTD3 /* high active */
|
||||||
#define ISP_MOSI PORTB5
|
|
||||||
#define ISP_MISO PORTB6
|
|
||||||
#define ISP_SCK PORTB7
|
|
||||||
#define RESET_IN PORTD3
|
|
||||||
|
|
||||||
struct {
|
|
||||||
uint8_t id; /* device id */
|
|
||||||
uint8_t pagemask; /* bitmask of one flash-page */
|
|
||||||
uint8_t pollcode; /* value of an empty flash-cell */
|
|
||||||
|
|
||||||
} devices[] = {
|
|
||||||
|
|
||||||
// { 0x20, 0x00, 0x7F }, /* at90s2313 (no paging, reads 0x7F back) */
|
|
||||||
{ 0x20, 0x0F, 0xFF }, /* tiny24 (16 words/page) */
|
|
||||||
{ 0x38, 0x00, 0x7F }, /* at90s8515 (no paging, reads 0x7F back) */
|
|
||||||
{ 0x43, 0x7F, 0xFF }, /* mega128 (128 words/page) */
|
|
||||||
{ 0x72, 0x3F, 0xFF }, /* mega32 (64 words/page) */
|
|
||||||
{ 0x74, 0x3F, 0xFF }, /* mega16 (64 words/page) */
|
|
||||||
{ 0x76, 0x1F, 0xFF }, /* mega8 (32 words/page) */
|
|
||||||
{ 0x00, 0x00, 0x00 },
|
|
||||||
};
|
|
||||||
|
|
||||||
#include <util/delay.h>
|
#include <util/delay.h>
|
||||||
#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)
|
||||||
|
|
||||||
|
/* F_CPU /4 (1.8432MHz) */
|
||||||
|
#define SPI_MODE4 ((1<<SPE) | (1<<MSTR))
|
||||||
|
/* F_CPU /16 (460.8kHz) */
|
||||||
|
#define SPI_MODE3 ((1<<SPE) | (1<<MSTR) | (1<<SPR1))
|
||||||
|
/* F_CPU /64 (115.2kHz) */
|
||||||
|
#define SPI_MODE2 ((1<<SPE) | (1<<MSTR) | (1<<SPR0))
|
||||||
|
/* F_CPU /128 (57.6kHz) */
|
||||||
|
#define SPI_MODE1 ((1<<SPE) | (1<<MSTR) | (1<<SPR1) | (1<<SPR0))
|
||||||
|
|
||||||
|
#define POLL_00 0x01 /* value 0x00 can not be polled from flash/eeprom */
|
||||||
|
#define POLL_7F 0x02 /* value 0x7F can not be polled from flash/eeprom */
|
||||||
|
#define POLL_80 0x04 /* value 0x80 can not be polled from flash/eeprom */
|
||||||
|
#define POLL_FF 0x08 /* value 0xFF can not be polled from flash/eeprom */
|
||||||
|
|
||||||
|
struct _device {
|
||||||
|
uint8_t sig[3]; /* device signature */
|
||||||
|
uint8_t devcode; /* avr910 device code */
|
||||||
|
uint16_t pagemask; /* pagemask */
|
||||||
|
uint16_t flags; /* quirks for this device */
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct _device device;
|
||||||
|
|
||||||
|
static struct _device devices[] PROGMEM = {
|
||||||
|
{ { 0x1E, 0x90, 0x01 }, 0x13, 0x00, POLL_00 | POLL_FF }, /* at90s1200 */
|
||||||
|
|
||||||
|
{ { 0x1E, 0x91, 0x01 }, 0x20, 0x00, POLL_7F | POLL_80 | POLL_FF }, /* at90s2313 */
|
||||||
|
{ { 0x1E, 0x91, 0x08 }, 0x20, 0x0F, POLL_FF }, /* tiny25 (at90s2313 devcode) */
|
||||||
|
{ { 0x1E, 0x91, 0x09 }, 0x5E, 0x0F, POLL_FF }, /* tiny26 */
|
||||||
|
{ { 0x1E, 0x91, 0x0A }, 0x5E, 0x0F, POLL_FF }, /* tiny2313 (tiny26 devcode) */
|
||||||
|
{ { 0x1E, 0x91, 0x0B }, 0x20, 0x0F, POLL_FF }, /* tiny24 (at90s2313 devcode) */
|
||||||
|
|
||||||
|
{ { 0x1E, 0x92, 0x06 }, 0x20, 0x1F, POLL_FF }, /* tiny45 (at90s2313 devcode) */
|
||||||
|
{ { 0x1E, 0x92, 0x07 }, 0x20, 0x1F, POLL_FF }, /* tiny44 (at90s2313 devcode) */
|
||||||
|
|
||||||
|
{ { 0x1E, 0x93, 0x01 }, 0x38, 0x00, POLL_7F | POLL_80 | POLL_FF }, /* at90s8515 */
|
||||||
|
{ { 0x1E, 0x93, 0x07 }, 0x76, 0x1F, POLL_00 | POLL_FF }, /* mega8 */
|
||||||
|
{ { 0x1E, 0x93, 0x0A }, 0xFF, 0x1F, POLL_FF }, /* mega88 (no devcode) */
|
||||||
|
{ { 0x1E, 0x93, 0x0B }, 0x20, 0x1F, POLL_FF }, /* tiny85 (at90s2313 devcode) */
|
||||||
|
{ { 0x1E, 0x93, 0x0C }, 0x20, 0x1F, POLL_FF }, /* tiny84 (at90s2313 devcode) */
|
||||||
|
|
||||||
|
{ { 0x1E, 0x94, 0x03 }, 0x74, 0x3F, POLL_FF }, /* mega16 */
|
||||||
|
{ { 0x1E, 0x94, 0x06 }, 0xFF, 0x3F, POLL_FF }, /* mega168 (no devcode) */
|
||||||
|
|
||||||
|
{ { 0x1E, 0x95, 0x02 }, 0x72, 0x3F, POLL_FF }, /* mega32 */
|
||||||
|
|
||||||
|
{ { 0x1E, 0x96, 0x02 }, 0x45, 0x7F, POLL_FF }, /* mega64 */
|
||||||
|
{ { 0x1E, 0x96, 0x09 }, 0x74, 0x7F, POLL_FF }, /* mega644 (mega16 devcode) */
|
||||||
|
{ { 0x1E, 0x96, 0x0A }, 0x74, 0x7F, POLL_FF }, /* mega644p (mega16 devcode) */
|
||||||
|
|
||||||
|
{ { 0x1E, 0x97, 0x01 }, 0x41, 0x7F, POLL_7F | POLL_80 | POLL_FF }, /* mega103 */
|
||||||
|
{ { 0x1E, 0x97, 0x02 }, 0x43, 0x7F, POLL_FF }, /* mega128 */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* sorted devcodes from devices[], terminated with 0x00 */
|
||||||
|
static uint8_t devcodes[] PROGMEM = { 0x13, 0x20, 0x38, 0x41, 0x43, 0x45, 0x5E, 0x72, 0x74, 0x76, 0x00 };
|
||||||
|
|
||||||
|
#define EV_NONE 0
|
||||||
|
#define EV_STATE_ENTER 1
|
||||||
|
#define EV_BUTTON_PRESSED 2
|
||||||
|
#define EV_BUTTON_RELEASED 3
|
||||||
|
#define EV_TIMEOUT 4
|
||||||
|
|
||||||
|
#define STATE_IDLE 0 /* nothing */
|
||||||
|
#define STATE_PRESSED 1 /* reset_in pressed, generating 50ms isp_reset pulse */
|
||||||
|
#define STATE_PRESSED2 2 /* reset_in still pressed, isp_reset pulse complete */
|
||||||
|
#define STATE_SPEED1 3 /* spi speed setting 1 */
|
||||||
|
#define STATE_SPEED2 4
|
||||||
|
#define STATE_SPEED3 5
|
||||||
|
#define STATE_SPEED4 6
|
||||||
|
|
||||||
#define LED_OFF 0x00
|
#define LED_OFF 0x00
|
||||||
#define LED_ON 0x01
|
#define LED_SLOW 0x20
|
||||||
#define LED_FAST 0x02
|
#define LED_FAST 0x08
|
||||||
#define LED_SLOW 0x03
|
#define LED_ON 0x80
|
||||||
|
#define LED_SPEED1 0x20
|
||||||
|
#define LED_SPEED2 0x10
|
||||||
|
#define LED_SPEED3 0x08
|
||||||
|
#define LED_SPEED4 0x04
|
||||||
|
|
||||||
#define CMD_PROG_ENABLE_1 0xAC
|
#define CMD_PROG_ENABLE_1 0xAC
|
||||||
#define CMD_PROG_ENABLE_2 0x53
|
#define CMD_PROG_ENABLE_2 0x53
|
||||||
@ -95,16 +165,11 @@ struct {
|
|||||||
#define CMD_WRITE_FUSE_E_1 0xAC /* not used */
|
#define CMD_WRITE_FUSE_E_1 0xAC /* not used */
|
||||||
#define CMD_WRITE_FUSE_E_2 0xA4 /* not used */
|
#define CMD_WRITE_FUSE_E_2 0xA4 /* not used */
|
||||||
|
|
||||||
static uint16_t lastaddr;
|
static volatile uint8_t led_mode;
|
||||||
static uint8_t lastcmd;
|
|
||||||
static uint8_t lastval;
|
|
||||||
static uint8_t pollcode = 0xFF;
|
|
||||||
|
|
||||||
/* toggle LED */
|
static uint8_t last_cmd;
|
||||||
ISR(SIG_OUTPUT_COMPARE1A)
|
static uint8_t last_val;
|
||||||
{
|
static uint16_t last_addr;
|
||||||
PORTB ^= (1<<ISP_LED);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send one byte to PC */
|
/* Send one byte to PC */
|
||||||
static void ser_send(uint8_t data)
|
static void ser_send(uint8_t data)
|
||||||
@ -120,12 +185,6 @@ static uint8_t ser_recv(void)
|
|||||||
return UDR;
|
return UDR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if receiver ready */
|
|
||||||
static uint8_t ser_recv_ready(void)
|
|
||||||
{
|
|
||||||
return bit_is_set(UCSRA, RXC);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send one byte to target, and return received one */
|
/* Send one byte to target, and return received one */
|
||||||
static uint8_t spi_rxtx(uint8_t val)
|
static uint8_t spi_rxtx(uint8_t val)
|
||||||
{
|
{
|
||||||
@ -134,35 +193,6 @@ static uint8_t spi_rxtx(uint8_t val)
|
|||||||
return SPDR;
|
return SPDR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set LED mode */
|
|
||||||
static void led_mode(uint8_t mode)
|
|
||||||
{
|
|
||||||
static uint8_t oldmode = LED_OFF;
|
|
||||||
|
|
||||||
if (mode == oldmode) {
|
|
||||||
return;
|
|
||||||
|
|
||||||
} else if (mode == LED_ON) {
|
|
||||||
TCCR1B = 0x00;
|
|
||||||
PORTB &= ~(1<<ISP_LED);
|
|
||||||
|
|
||||||
} else if (mode == LED_OFF) {
|
|
||||||
TCCR1B = 0x00;
|
|
||||||
PORTB |= (1<<ISP_LED);
|
|
||||||
|
|
||||||
} else if (mode == LED_FAST) {
|
|
||||||
/* timer1: F_CPU /64, CTC mode via OutputCompare A, 10Hz */
|
|
||||||
OCR1A = (F_CPU / (64 * 10));
|
|
||||||
TCCR1B = (1<<WGM12) | (1<<CS11) | (1<<CS10);
|
|
||||||
|
|
||||||
} else if (mode == LED_SLOW) {
|
|
||||||
/* timer1: FCPU /64, CTC mode via OutputCompare A, 4Hz */
|
|
||||||
OCR1A = (F_CPU / (64 * 4));
|
|
||||||
TCCR1B = (1<<WGM12) | (1<<CS11) | (1<<CS10);
|
|
||||||
}
|
|
||||||
oldmode = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Control reset and SPI lines */
|
/* Control reset and SPI lines */
|
||||||
static void set_reset(uint8_t mode)
|
static void set_reset(uint8_t mode)
|
||||||
{
|
{
|
||||||
@ -176,9 +206,6 @@ static void set_reset(uint8_t mode)
|
|||||||
DDRB |= ((1<<ISP_SCK) | (1<<ISP_MOSI) | (1<<ISP_RESET));
|
DDRB |= ((1<<ISP_SCK) | (1<<ISP_MOSI) | (1<<ISP_RESET));
|
||||||
PORTB &= ~(1<<ISP_RESET);
|
PORTB &= ~(1<<ISP_RESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
_delay_ms(25);
|
|
||||||
_delay_ms(25);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* writes a byte to target flash/eeprom */
|
/* writes a byte to target flash/eeprom */
|
||||||
@ -190,9 +217,9 @@ static void mem_write(uint8_t cmd, uint16_t addr, uint8_t val)
|
|||||||
spi_rxtx(val);
|
spi_rxtx(val);
|
||||||
|
|
||||||
/* remember values for polling */
|
/* remember values for polling */
|
||||||
lastcmd = cmd;
|
last_cmd = cmd;
|
||||||
lastaddr = addr;
|
last_addr = addr;
|
||||||
lastval = val;
|
last_val = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read a byte from target flash/eeprom */
|
/* read a byte from target flash/eeprom */
|
||||||
@ -209,94 +236,84 @@ static void poll(void)
|
|||||||
{
|
{
|
||||||
uint8_t cmd, val, poll = 0xFF;
|
uint8_t cmd, val, poll = 0xFF;
|
||||||
|
|
||||||
if (lastcmd == CMD_WRITE_EEPROM) {
|
if (((last_val == 0x00) && (device.flags & POLL_00)) ||
|
||||||
/* check if we can poll */
|
((last_val == 0x7F) && (device.flags & POLL_7F)) ||
|
||||||
if (lastval == pollcode || lastval == 0x7F || lastval == 0x80) {
|
((last_val == 0x80) && (device.flags & POLL_80)) ||
|
||||||
|
((last_val == 0xFF) && (device.flags & POLL_FF))
|
||||||
|
) {
|
||||||
/* wait default time */
|
/* wait default time */
|
||||||
_delay_ms(10);
|
_delay_ms(15);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (last_cmd == CMD_WRITE_EEPROM) {
|
||||||
cmd = CMD_READ_EEPROM;
|
cmd = CMD_READ_EEPROM;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* check if we can poll */
|
|
||||||
if (lastval == pollcode) {
|
|
||||||
/* wait default time */
|
|
||||||
_delay_ms(10);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* CMD_WRITE_FLASH -> CMD_READ_FLASH */
|
/* CMD_WRITE_FLASH -> CMD_READ_FLASH */
|
||||||
cmd = (lastcmd & 0x08) | 0x20;
|
cmd = (last_cmd & 0x08) | 0x20;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* poll until we get correct value */
|
/* poll until we get correct value */
|
||||||
do {
|
do {
|
||||||
val = mem_read(cmd, lastaddr);
|
val = mem_read(cmd, last_addr);
|
||||||
} while ((val != lastval) && poll--);
|
} while ((val != last_val) && poll--);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void)
|
|
||||||
|
static void mem_pagewrite(uint16_t addr)
|
||||||
|
{
|
||||||
|
spi_rxtx(CMD_WRITE_FLASH_PAGE);
|
||||||
|
spi_rxtx(addr >> 8);
|
||||||
|
spi_rxtx(addr & 0xFF);
|
||||||
|
spi_rxtx(0x00);
|
||||||
|
|
||||||
|
poll();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cmdloop(void)
|
||||||
{
|
{
|
||||||
static uint8_t page_buf[256];
|
static uint8_t page_buf[256];
|
||||||
uint16_t addr = 0;
|
uint16_t addr = 0;
|
||||||
uint8_t device = 0, pagemask = 0;
|
|
||||||
|
|
||||||
/* ISP_RESET and ISP_LED are outputs, pullup SlaveSelect */
|
|
||||||
PORTB = (1<<ISP_RESET) | (1<<ISP_LED) | (1<<PORTB4);
|
|
||||||
DDRB = (1<<ISP_RESET) | (1<<ISP_LED);
|
|
||||||
|
|
||||||
/* Set baud rate */
|
|
||||||
UBRRH = (UART_CALC_BAUDRATE(BAUDRATE)>>8) & 0xFF;
|
|
||||||
UBRRL = (UART_CALC_BAUDRATE(BAUDRATE) & 0xFF);
|
|
||||||
|
|
||||||
/* enable usart with 8n1 */
|
|
||||||
UCSRB = (1<<TXEN) | (1<<RXEN);
|
|
||||||
UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
|
|
||||||
|
|
||||||
/* enable SPI master mode */
|
|
||||||
SPCR = SPI_MODE;
|
|
||||||
|
|
||||||
/* enable timer1 OutputCompare A interrupt (CTC hit) */
|
|
||||||
TIMSK = (1<<OCIE1A);
|
|
||||||
sei();
|
|
||||||
|
|
||||||
/* disable ISP_RESET */
|
/* disable ISP_RESET */
|
||||||
set_reset(1);
|
set_reset(1);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
uint8_t pulse = 0;
|
|
||||||
|
|
||||||
while (!ser_recv_ready()) {
|
|
||||||
/* reset the target */
|
|
||||||
if (PIND & (1<<RESET_IN)) {
|
|
||||||
if (!pulse) {
|
|
||||||
led_mode(LED_ON);
|
|
||||||
set_reset(0);
|
|
||||||
set_reset(1);
|
|
||||||
led_mode(LED_OFF);
|
|
||||||
pulse = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
pulse = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (ser_recv()) {
|
switch (ser_recv()) {
|
||||||
/* Enter programming mode */
|
/* Enter programming mode */
|
||||||
case 'P': {
|
case 'P': {
|
||||||
uint8_t sync, count = 0x20;
|
uint8_t sync, count = 0x20;
|
||||||
led_mode(LED_ON);
|
led_mode = LED_ON;
|
||||||
do {
|
do {
|
||||||
set_reset(1);
|
set_reset(1);
|
||||||
|
_delay_ms(50);
|
||||||
set_reset(0);
|
set_reset(0);
|
||||||
|
_delay_ms(50);
|
||||||
|
|
||||||
spi_rxtx(CMD_PROG_ENABLE_1);
|
spi_rxtx(CMD_PROG_ENABLE_1);
|
||||||
spi_rxtx(CMD_PROG_ENABLE_2);
|
spi_rxtx(CMD_PROG_ENABLE_2);
|
||||||
sync = spi_rxtx(0x00);
|
sync = spi_rxtx(0x00);
|
||||||
spi_rxtx(0x00);
|
spi_rxtx(0x00);
|
||||||
|
|
||||||
} while (sync != 0x53 && count--);
|
} while (sync != CMD_PROG_ENABLE_2 && count--);
|
||||||
|
|
||||||
|
memset(&device, 0x00, sizeof(struct _device));
|
||||||
|
|
||||||
|
if (sync == CMD_PROG_ENABLE_2) {
|
||||||
|
uint8_t i, sig[3];
|
||||||
|
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
sig[i] = mem_read(CMD_READ_SIG_1, (CMD_READ_SIG_2 << 8) | i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(devices); i++) {
|
||||||
|
if (memcmp_P(sig, devices[i].sig, sizeof(sig)) == 0) {
|
||||||
|
memcpy_P(&device, &devices[i], sizeof(struct _device));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ser_send('\r');
|
ser_send('\r');
|
||||||
break;
|
break;
|
||||||
@ -316,24 +333,26 @@ int main(void)
|
|||||||
|
|
||||||
/* Write program memory, low byte */
|
/* Write program memory, low byte */
|
||||||
case 'c':
|
case 'c':
|
||||||
led_mode(LED_FAST);
|
led_mode = LED_FAST;
|
||||||
mem_write(CMD_LOAD_FLASH_LO, addr, ser_recv());
|
mem_write(CMD_LOAD_FLASH_LO, addr, ser_recv());
|
||||||
|
|
||||||
/* poll on byte addressed targets */
|
/* poll on byte addressed targets */
|
||||||
if (!pagemask)
|
if (device.pagemask == 0x00) {
|
||||||
poll();
|
poll();
|
||||||
|
}
|
||||||
|
|
||||||
ser_send('\r');
|
ser_send('\r');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Write program memory, high byte */
|
/* Write program memory, high byte */
|
||||||
case 'C':
|
case 'C':
|
||||||
led_mode(LED_FAST);
|
led_mode = LED_FAST;
|
||||||
mem_write(CMD_LOAD_FLASH_HI, addr, ser_recv());
|
mem_write(CMD_LOAD_FLASH_HI, addr, ser_recv());
|
||||||
|
|
||||||
/* poll on byte addressed targets */
|
/* poll on byte addressed targets */
|
||||||
if (!pagemask)
|
if (device.pagemask == 0x00) {
|
||||||
poll();
|
poll();
|
||||||
|
}
|
||||||
|
|
||||||
addr++;
|
addr++;
|
||||||
ser_send('\r');
|
ser_send('\r');
|
||||||
@ -341,14 +360,8 @@ int main(void)
|
|||||||
|
|
||||||
/* Issue Page Write */
|
/* Issue Page Write */
|
||||||
case 'm':
|
case 'm':
|
||||||
led_mode(LED_FAST);
|
led_mode = LED_FAST;
|
||||||
spi_rxtx(CMD_WRITE_FLASH_PAGE);
|
mem_pagewrite(last_addr);
|
||||||
spi_rxtx(lastaddr >> 8);
|
|
||||||
spi_rxtx(lastaddr & 0xFF);
|
|
||||||
spi_rxtx(0x00);
|
|
||||||
|
|
||||||
poll();
|
|
||||||
|
|
||||||
ser_send('\r');
|
ser_send('\r');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -360,7 +373,7 @@ int main(void)
|
|||||||
|
|
||||||
/* Read program memory */
|
/* Read program memory */
|
||||||
case 'R':
|
case 'R':
|
||||||
led_mode(LED_SLOW);
|
led_mode = LED_SLOW;
|
||||||
ser_send(mem_read(CMD_READ_FLASH_HI, addr));
|
ser_send(mem_read(CMD_READ_FLASH_HI, addr));
|
||||||
ser_send(mem_read(CMD_READ_FLASH_LO, addr));
|
ser_send(mem_read(CMD_READ_FLASH_LO, addr));
|
||||||
addr++;
|
addr++;
|
||||||
@ -368,14 +381,14 @@ int main(void)
|
|||||||
|
|
||||||
/* Read data memory */
|
/* Read data memory */
|
||||||
case 'd':
|
case 'd':
|
||||||
led_mode(LED_SLOW);
|
led_mode = LED_SLOW;
|
||||||
ser_send(mem_read(CMD_READ_EEPROM, addr));
|
ser_send(mem_read(CMD_READ_EEPROM, addr));
|
||||||
addr++;
|
addr++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Write data memory */
|
/* Write data memory */
|
||||||
case 'D':
|
case 'D':
|
||||||
led_mode(LED_FAST);
|
led_mode = LED_FAST;
|
||||||
mem_write(CMD_WRITE_EEPROM, addr, ser_recv());
|
mem_write(CMD_WRITE_EEPROM, addr, ser_recv());
|
||||||
poll();
|
poll();
|
||||||
|
|
||||||
@ -390,7 +403,7 @@ int main(void)
|
|||||||
spi_rxtx(0x00);
|
spi_rxtx(0x00);
|
||||||
spi_rxtx(0x00);
|
spi_rxtx(0x00);
|
||||||
|
|
||||||
_delay_ms(25);
|
_delay_ms(10);
|
||||||
ser_send('\r');
|
ser_send('\r');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -402,7 +415,7 @@ int main(void)
|
|||||||
spi_rxtx(0x00);
|
spi_rxtx(0x00);
|
||||||
spi_rxtx(val);
|
spi_rxtx(val);
|
||||||
|
|
||||||
_delay_ms(25);
|
_delay_ms(10);
|
||||||
ser_send('\r');
|
ser_send('\r');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -428,25 +441,13 @@ int main(void)
|
|||||||
/* Exit Bootloader */
|
/* Exit Bootloader */
|
||||||
case 'E':
|
case 'E':
|
||||||
set_reset(1);
|
set_reset(1);
|
||||||
led_mode(LED_OFF);
|
led_mode = LED_OFF;
|
||||||
ser_send('\r');
|
ser_send('\r');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Select device type */
|
/* Select device type */
|
||||||
case 'T': {
|
case 'T': {
|
||||||
uint8_t val, i = 0;
|
ser_recv(); // ignore
|
||||||
val = ser_recv();
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (val == devices[i].id) {
|
|
||||||
device = val;
|
|
||||||
pagemask = devices[i].pagemask;
|
|
||||||
pollcode = devices[i].pollcode;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
} while (devices[i++].id);
|
|
||||||
|
|
||||||
ser_send('\r');
|
ser_send('\r');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -455,18 +456,17 @@ int main(void)
|
|||||||
case 's': {
|
case 's': {
|
||||||
uint8_t i = 2;
|
uint8_t i = 2;
|
||||||
do {
|
do {
|
||||||
ser_send(mem_read(CMD_READ_SIG_1, (CMD_READ_SIG_2 << 8) | i));
|
ser_send(device.sig[i]);
|
||||||
} while (i--);
|
} while (i--);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return supported device codes */
|
/* Return supported device codes */
|
||||||
case 't': {
|
case 't': {
|
||||||
uint8_t val, i = 0;
|
uint8_t i;
|
||||||
do {
|
for (i = 0; i < ARRAY_SIZE(devcodes); i++) {
|
||||||
val = devices[i++].id;
|
ser_send(pgm_read_byte(&devcodes[i]));
|
||||||
ser_send(val);
|
}
|
||||||
} while (val);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -501,28 +501,29 @@ int main(void)
|
|||||||
/* Set LED */
|
/* Set LED */
|
||||||
case 'x':
|
case 'x':
|
||||||
ser_recv();
|
ser_recv();
|
||||||
led_mode(LED_ON);
|
led_mode = LED_ON;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Clear LED */
|
/* Clear LED */
|
||||||
case 'y':
|
case 'y':
|
||||||
ser_recv();
|
ser_recv();
|
||||||
led_mode(LED_OFF);
|
led_mode = LED_OFF;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Report Block write Mode */
|
/* Report Block write Mode */
|
||||||
case 'b':
|
case 'b': {
|
||||||
ser_send('Y');
|
ser_send('Y');
|
||||||
ser_send(sizeof(page_buf) >> 8);
|
ser_send(sizeof(page_buf) >> 8);
|
||||||
ser_send(sizeof(page_buf) & 0xFF);
|
ser_send(sizeof(page_buf) & 0xFF);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Block Write */
|
/* Block Write */
|
||||||
case 'B': {
|
case 'B': {
|
||||||
uint16_t size, i;
|
uint16_t size, i;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
|
|
||||||
led_mode(LED_FAST);
|
led_mode = LED_FAST;
|
||||||
|
|
||||||
size = ser_recv() << 8;
|
size = ser_recv() << 8;
|
||||||
size |= ser_recv();
|
size |= ser_recv();
|
||||||
@ -538,25 +539,13 @@ int main(void)
|
|||||||
|
|
||||||
addr++;
|
addr++;
|
||||||
|
|
||||||
/* page write on page-boundry */
|
if ((addr & device.pagemask) == 0x00) {
|
||||||
if ((addr & pagemask) == 0x00) {
|
mem_pagewrite(last_addr);
|
||||||
spi_rxtx(CMD_WRITE_FLASH_PAGE);
|
|
||||||
spi_rxtx(lastaddr >> 8);
|
|
||||||
spi_rxtx(lastaddr & 0xFF);
|
|
||||||
spi_rxtx(0x00);
|
|
||||||
|
|
||||||
poll();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* last page */
|
|
||||||
if (size != sizeof(page_buf)) {
|
if (size != sizeof(page_buf)) {
|
||||||
spi_rxtx(CMD_WRITE_FLASH_PAGE);
|
mem_pagewrite(last_addr);
|
||||||
spi_rxtx(lastaddr >> 8);
|
|
||||||
spi_rxtx(lastaddr & 0xFF);
|
|
||||||
spi_rxtx(0x00);
|
|
||||||
|
|
||||||
poll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (type == 'E') {
|
} else if (type == 'E') {
|
||||||
@ -575,7 +564,7 @@ int main(void)
|
|||||||
uint16_t size, i;
|
uint16_t size, i;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
|
|
||||||
led_mode(LED_SLOW);
|
led_mode = LED_SLOW;
|
||||||
|
|
||||||
size = ser_recv() << 8;
|
size = ser_recv() << 8;
|
||||||
size |= ser_recv();
|
size |= ser_recv();
|
||||||
@ -605,7 +594,7 @@ int main(void)
|
|||||||
spi_rxtx(0x00);
|
spi_rxtx(0x00);
|
||||||
spi_rxtx(val);
|
spi_rxtx(val);
|
||||||
|
|
||||||
_delay_ms(25);
|
_delay_ms(10);
|
||||||
ser_send('\r');
|
ser_send('\r');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -621,7 +610,7 @@ int main(void)
|
|||||||
spi_rxtx(val[1]);
|
spi_rxtx(val[1]);
|
||||||
ser_send(spi_rxtx(val[2]));
|
ser_send(spi_rxtx(val[2]));
|
||||||
|
|
||||||
_delay_ms(25);
|
_delay_ms(10);
|
||||||
ser_send('\r');
|
ser_send('\r');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -639,7 +628,7 @@ int main(void)
|
|||||||
spi_rxtx(val[2]);
|
spi_rxtx(val[2]);
|
||||||
ser_send(spi_rxtx(val[3]));
|
ser_send(spi_rxtx(val[3]));
|
||||||
|
|
||||||
_delay_ms(25);
|
_delay_ms(10);
|
||||||
ser_send('\r');
|
ser_send('\r');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -653,5 +642,219 @@ int main(void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t statemachine(uint8_t event)
|
||||||
|
{
|
||||||
|
static uint8_t oldstate;
|
||||||
|
uint8_t state = oldstate;
|
||||||
|
uint16_t timer;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (state != oldstate) {
|
||||||
|
event = EV_STATE_ENTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case STATE_IDLE:
|
||||||
|
if (event == EV_STATE_ENTER) {
|
||||||
|
led_mode = LED_OFF;
|
||||||
|
timer = 0xFFFF; /* stop timer */
|
||||||
|
|
||||||
|
} else if (event == EV_BUTTON_PRESSED) {
|
||||||
|
state = STATE_PRESSED;
|
||||||
|
set_reset(0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_PRESSED:
|
||||||
|
if (event == EV_STATE_ENTER) {
|
||||||
|
led_mode = LED_ON;
|
||||||
|
timer = 5; /* timeout 50ms (== reset length) */
|
||||||
|
|
||||||
|
} else if (event == EV_BUTTON_RELEASED) {
|
||||||
|
state = STATE_IDLE;
|
||||||
|
set_reset(1);
|
||||||
|
|
||||||
|
} else if (event == EV_TIMEOUT) {
|
||||||
|
state = STATE_PRESSED2;
|
||||||
|
set_reset(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_PRESSED2:
|
||||||
|
if (event == EV_STATE_ENTER) {
|
||||||
|
led_mode = LED_OFF;
|
||||||
|
timer = 500; /* timeout in 5s */
|
||||||
|
|
||||||
|
} else if (event == EV_BUTTON_RELEASED) {
|
||||||
|
state = STATE_IDLE;
|
||||||
|
|
||||||
|
} else if (event == EV_TIMEOUT) {
|
||||||
|
switch (SPCR) {
|
||||||
|
case SPI_MODE1:
|
||||||
|
state = STATE_SPEED1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SPI_MODE2:
|
||||||
|
state = STATE_SPEED2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SPI_MODE3:
|
||||||
|
state = STATE_SPEED3;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
case SPI_MODE4:
|
||||||
|
state = STATE_SPEED4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_SPEED1:
|
||||||
|
if (event == EV_STATE_ENTER) {
|
||||||
|
led_mode = LED_SPEED1;
|
||||||
|
timer = 500; /* timeout in 5s */
|
||||||
|
|
||||||
|
} else if (event == EV_BUTTON_PRESSED) {
|
||||||
|
state = STATE_SPEED2;
|
||||||
|
|
||||||
|
} else if (event == EV_TIMEOUT) {
|
||||||
|
state = STATE_IDLE;
|
||||||
|
SPCR = SPI_MODE1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_SPEED2:
|
||||||
|
if (event == EV_STATE_ENTER) {
|
||||||
|
led_mode = LED_SPEED2;
|
||||||
|
timer = 500; /* timeout in 5s */
|
||||||
|
|
||||||
|
} else if (event == EV_BUTTON_PRESSED) {
|
||||||
|
state = STATE_SPEED3;
|
||||||
|
|
||||||
|
} else if (event == EV_TIMEOUT) {
|
||||||
|
state = STATE_IDLE;
|
||||||
|
SPCR = SPI_MODE2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_SPEED3:
|
||||||
|
if (event == EV_STATE_ENTER) {
|
||||||
|
led_mode = LED_SPEED3;
|
||||||
|
timer = 500; /* timeout in 5s */
|
||||||
|
|
||||||
|
} else if (event == EV_BUTTON_PRESSED) {
|
||||||
|
state = STATE_SPEED4;
|
||||||
|
|
||||||
|
} else if (event == EV_TIMEOUT) {
|
||||||
|
state = STATE_IDLE;
|
||||||
|
SPCR = SPI_MODE3;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_SPEED4:
|
||||||
|
if (event == EV_STATE_ENTER) {
|
||||||
|
led_mode = LED_SPEED4;
|
||||||
|
timer = 500; /* timeout in 5s */
|
||||||
|
|
||||||
|
} else if (event == EV_BUTTON_PRESSED) {
|
||||||
|
state = STATE_SPEED1;
|
||||||
|
|
||||||
|
} else if (event == EV_TIMEOUT) {
|
||||||
|
state = STATE_IDLE;
|
||||||
|
SPCR = SPI_MODE4;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
state = STATE_IDLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event == EV_STATE_ENTER) {
|
||||||
|
oldstate = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (state != oldstate);
|
||||||
|
|
||||||
|
return timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* time keeping */
|
||||||
|
ISR(TIMER0_OVF_vect)
|
||||||
|
{
|
||||||
|
uint8_t event = EV_NONE;
|
||||||
|
|
||||||
|
/* restart timer */
|
||||||
|
TCNT0 = TIMER_RELOAD;
|
||||||
|
|
||||||
|
static uint8_t prev_pressed;
|
||||||
|
if (PIND & (1<<RESET_IN)) {
|
||||||
|
if (!prev_pressed) {
|
||||||
|
event = EV_BUTTON_PRESSED;
|
||||||
|
prev_pressed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (prev_pressed) {
|
||||||
|
event = EV_BUTTON_RELEASED;
|
||||||
|
prev_pressed = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t timer;
|
||||||
|
if (timer) {
|
||||||
|
timer--;
|
||||||
|
if (timer == 0) {
|
||||||
|
event = EV_TIMEOUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event != EV_NONE) {
|
||||||
|
uint16_t new_timer = statemachine(event);
|
||||||
|
if (new_timer == 0xFFFF) {
|
||||||
|
timer = 0;
|
||||||
|
|
||||||
|
} else if (new_timer > 0) {
|
||||||
|
timer = new_timer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update LED */
|
||||||
|
static uint8_t led_timer;
|
||||||
|
|
||||||
|
if (led_mode & ((led_timer++ & 0xFF) | 0x80)) {
|
||||||
|
PORTB &= ~(1<<ISP_LED);
|
||||||
|
} else {
|
||||||
|
PORTB |= (1<<ISP_LED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
/* ISP_RESET and ISP_LED are outputs, pullup SlaveSelect */
|
||||||
|
PORTB = (1<<ISP_RESET) | (1<<ISP_LED) | (1<<PORTB4);
|
||||||
|
DDRB = (1<<ISP_RESET) | (1<<ISP_LED);
|
||||||
|
|
||||||
|
/* Set baud rate */
|
||||||
|
UBRRH = (UART_CALC_BAUDRATE(BAUDRATE)>>8) & 0xFF;
|
||||||
|
UBRRL = (UART_CALC_BAUDRATE(BAUDRATE) & 0xFF);
|
||||||
|
|
||||||
|
/* enable usart with 8n1 */
|
||||||
|
UCSRB = (1<<TXEN) | (1<<RXEN);
|
||||||
|
UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
|
||||||
|
|
||||||
|
/* enable SPI master mode */
|
||||||
|
SPCR = SPI_MODE4;
|
||||||
|
|
||||||
|
/* timer0, FCPU/1024, overflow interrupt */
|
||||||
|
TCCR0 = (1<<CS02) | (1<<CS00);
|
||||||
|
TIMSK = (1<<TOIE0);
|
||||||
|
|
||||||
|
sei();
|
||||||
|
|
||||||
|
cmdloop();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user