initial version
This commit is contained in:
commit
e7b67a0aa7
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
*.o
|
||||||
|
*.elf
|
||||||
|
*.bin
|
||||||
|
*.hex
|
||||||
|
*.lst
|
||||||
|
*.lss
|
||||||
|
*.map
|
||||||
|
ldscript-no-vectors-*.x
|
104
Makefile
Normal file
104
Makefile
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
CC := avr-gcc
|
||||||
|
LD := avr-ld
|
||||||
|
OBJCOPY := avr-objcopy
|
||||||
|
OBJDUMP := avr-objdump
|
||||||
|
SIZE := avr-size
|
||||||
|
|
||||||
|
TARGET = uartboot
|
||||||
|
SOURCE = $(wildcard *.c)
|
||||||
|
|
||||||
|
#CONFIG = ispprog
|
||||||
|
#CONFIG = flightctrl
|
||||||
|
#CONFIG = funkstuff
|
||||||
|
CONFIG = ispprog2
|
||||||
|
|
||||||
|
AVRDUDE_PROG := -c avr910 -b 115200 -P /dev/ttyUSB0
|
||||||
|
#AVRDUDE_PROG := -c dragon_isp -P usb
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
ifeq ($(CONFIG), ispprog)
|
||||||
|
MCU=atmega16
|
||||||
|
AVRDUDE_MCU=m16
|
||||||
|
|
||||||
|
# (7.3728MHz ext. crystal)
|
||||||
|
AVRDUDE_FUSES=lfuse:w:0xff:m hfuse:w:0xda:m
|
||||||
|
BOOTLOADER_START=0x3C00
|
||||||
|
endif
|
||||||
|
|
||||||
|
# -------------------------
|
||||||
|
|
||||||
|
ifeq ($(CONFIG), flightctrl)
|
||||||
|
MCU=atmega644p
|
||||||
|
AVRDUDE_MCU=m644p
|
||||||
|
|
||||||
|
# (20MHz ext. Crystal, 2.7V BOD)
|
||||||
|
AVRDUDE_FUSES=lfuse:w:0xff:m hfuse:w:0xdc:m efuse:w:0xfd:m
|
||||||
|
BOOTLOADER_START=0xF800
|
||||||
|
endif
|
||||||
|
|
||||||
|
# -------------------------
|
||||||
|
|
||||||
|
ifeq ($(CONFIG), funkstuff)
|
||||||
|
MCU=atmega88
|
||||||
|
AVRDUDE_MCU=m88 -F
|
||||||
|
|
||||||
|
# (ext. crystal)
|
||||||
|
#AVRDUDE_FUSES=lfuse:w:0x84:m hfuse:w:0xda:m
|
||||||
|
BOOTLOADER_START=0x1C00
|
||||||
|
endif
|
||||||
|
|
||||||
|
# -------------------------
|
||||||
|
|
||||||
|
ifeq ($(CONFIG), ispprog2)
|
||||||
|
MCU=atmega328p
|
||||||
|
AVRDUDE_MCU=m328p -F
|
||||||
|
|
||||||
|
# (8MHz internal osc., 2.7V BOD)
|
||||||
|
AVRDUDE_FUSES=lfuse:w:0xe2:m hfuse:w:0xdc:m efuse:w:0x02:m
|
||||||
|
BOOTLOADER_START=0x7C00
|
||||||
|
endif
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CFLAGS = -pipe -g -Os -mmcu=$(MCU) -Wall
|
||||||
|
CFLAGS += -fdata-sections -ffunction-sections
|
||||||
|
CFLAGS += -Wa,-adhlns=$(*F).lst
|
||||||
|
CFLAGS += -DBOOTLOADER_START=$(BOOTLOADER_START) -DCONFIG_$(CONFIG)=1
|
||||||
|
LDFLAGS = -Wl,-Map,$(@:.elf=.map),--cref,--section-start=.text=$(BOOTLOADER_START)
|
||||||
|
LDFLAGS += -Wl,--relax,--gc-sections
|
||||||
|
|
||||||
|
LDSCRIPT := $(shell LANG=C $(CC) $(CFLAGS) -Wl,--verbose 2> /dev/null | awk '/^opened script file (.*)$$/{ print $$4 }')
|
||||||
|
LDSCRIPT_NOVECT := ldscript-no-vectors-$(notdir $(LDSCRIPT))
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
$(TARGET): $(TARGET).elf
|
||||||
|
@$(SIZE) -B -x --mcu=$(MCU) $<
|
||||||
|
|
||||||
|
$(TARGET).elf: $(SOURCE:.c=.o) | $(LDSCRIPT_NOVECT)
|
||||||
|
@echo " Linking file: $@"
|
||||||
|
@$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-T$(LDSCRIPT_NOVECT) -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 $<
|
||||||
|
|
||||||
|
# remove interrupt vector section from avr-libc linker script
|
||||||
|
# (remove all lines with *vectors* and insert DISCARD line above .text declaration)
|
||||||
|
$(LDSCRIPT_NOVECT): $(LDSCRIPT) $(MAKEFILE_LIST)
|
||||||
|
@echo " Creating: $@"
|
||||||
|
@sed -e '/.*vectors.*/d' -e 's/\(^[ \t]*\)\(.text[ \t]*\:\)$$/\1\/DISCARD\/ : { *(.vectors) }\n\1\2/g' $< > $@
|
||||||
|
# -@diff -uNr $< $@ > $@.diff
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(SOURCE:.c=.o) $(SOURCE:.c=.lst) $(addprefix $(TARGET), .elf .map .lss .hex .bin) ldscript-no-vectors-*
|
||||||
|
|
||||||
|
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))
|
544
main.c
Normal file
544
main.c
Normal file
@ -0,0 +1,544 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 10/2014 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>
|
||||||
|
#include <avr/boot.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
#include <avr/wdt.h>
|
||||||
|
|
||||||
|
/* *********************************************************************** */
|
||||||
|
#if defined(CONFIG_ispprog)
|
||||||
|
/*
|
||||||
|
* using ATmega16 @7.3728MHz:
|
||||||
|
* Fuse H: 0xDA (512 words bootloader, jtag disabled)
|
||||||
|
* Fuse L: 0xFF (ext. Crystal)
|
||||||
|
*/
|
||||||
|
#define F_CPU 7372800
|
||||||
|
#define BAUDRATE 19200
|
||||||
|
#define DEVCODE 0x74
|
||||||
|
|
||||||
|
/* 100 * 10ms => 1000ms */
|
||||||
|
//#define TIMEOUT 100
|
||||||
|
|
||||||
|
/* enter bootloader if PIND3 is high */
|
||||||
|
#define ISP_DDR DDRD
|
||||||
|
#define ISP_PIN PIND
|
||||||
|
#define ISP_PORT PORTD
|
||||||
|
#define ISP_NUM PIND3
|
||||||
|
#define ISP_POL 1
|
||||||
|
|
||||||
|
/* low active led on PORTB3 */
|
||||||
|
#define LED_DDR DDRB
|
||||||
|
#define LED_PORT PORTB
|
||||||
|
#define LED_NUM PORTB3
|
||||||
|
#define LED_POL 0
|
||||||
|
|
||||||
|
/* *********************************************************************** */
|
||||||
|
#elif defined(CONFIG_flightctrl)
|
||||||
|
/*
|
||||||
|
* using ATmega644 @20MHz:
|
||||||
|
* Fuse E: 0xFD (2.7V BOD)
|
||||||
|
* Fuse H: 0xDC (1024 words bootloader)
|
||||||
|
* Fuse L: 0xFF (ext. Crystal)
|
||||||
|
*/
|
||||||
|
#define F_CPU 20000000
|
||||||
|
#define BAUDRATE 57600
|
||||||
|
#define DEVCODE 0x74 /* mega16 devcode */
|
||||||
|
|
||||||
|
/* 100 * 10ms => 1000ms */
|
||||||
|
#define TIMEOUT 100
|
||||||
|
|
||||||
|
/* enter bootloader if PIND3 is high */
|
||||||
|
//#define ISP_DDR DDRD
|
||||||
|
//#define ISP_PIN PIND
|
||||||
|
//#define ISP_PORT PORTD
|
||||||
|
//#define ISP_NUM PIND3
|
||||||
|
//#define ISP_POL 1
|
||||||
|
|
||||||
|
/* high active led on PORTB1 */
|
||||||
|
#define LED_DDR DDRB
|
||||||
|
#define LED_PORT PORTB
|
||||||
|
#define LED_NUM PORTB1
|
||||||
|
#define LED_POL 1
|
||||||
|
|
||||||
|
/* support special MKBL commands */
|
||||||
|
#define SUPPORT_MKBL 1
|
||||||
|
|
||||||
|
/* *********************************************************************** */
|
||||||
|
#elif defined(CONFIG_funkstuff)
|
||||||
|
/*
|
||||||
|
* using ATmega88 @8MHz:
|
||||||
|
* Fuse E: 0xFA (2.7V BOD)
|
||||||
|
* Fuse H: 0xDD (512 words bootloader)
|
||||||
|
* Fuse L: 0xE2 (internal osc)
|
||||||
|
*/
|
||||||
|
#define F_CPU 8000000
|
||||||
|
#define BAUDRATE 19200
|
||||||
|
#define DEVCODE 0x76 /* mega8 devcode */
|
||||||
|
|
||||||
|
/* 100 * 10ms => 1000ms */
|
||||||
|
#define TIMEOUT 100
|
||||||
|
|
||||||
|
/* enter bootloader if PIND3 is high */
|
||||||
|
//#define ISP_DDR DDRD
|
||||||
|
//#define ISP_PIN PIND
|
||||||
|
//#define ISP_PORT PORTD
|
||||||
|
//#define ISP_NUM PIND3
|
||||||
|
//#define ISP_POL 1
|
||||||
|
|
||||||
|
/* low active led on PORTB3 */
|
||||||
|
//#define LED_DDR DDRB
|
||||||
|
//#define LED_PORT PORTB
|
||||||
|
//#define LED_NUM PORTB3
|
||||||
|
//#define LED_POL 0
|
||||||
|
|
||||||
|
/* *********************************************************************** */
|
||||||
|
#elif defined(CONFIG_ispprog2)
|
||||||
|
/*
|
||||||
|
* using ATmega328P @8MHz:
|
||||||
|
* Fuse E: 0xFA (2.7V BOD)
|
||||||
|
* Fuse H: 0xDC (512 words bootloader)
|
||||||
|
* Fuse L: 0xE2 (internal osc)
|
||||||
|
*/
|
||||||
|
#define F_CPU 8000000
|
||||||
|
#define BAUDRATE 115200
|
||||||
|
#define DEVCODE 0x72 /* mega32 devcode */
|
||||||
|
|
||||||
|
/* 100 * 10ms => 1000ms */
|
||||||
|
#define TIMEOUT 100
|
||||||
|
|
||||||
|
/* enter bootloader if PINB1 is low */
|
||||||
|
#define ISP_DDR DDRB
|
||||||
|
#define ISP_PIN PINB
|
||||||
|
#define ISP_PORT PORTB
|
||||||
|
#define ISP_NUM PINB1
|
||||||
|
#define ISP_POL 0
|
||||||
|
|
||||||
|
/* high active led on PORTB0 */
|
||||||
|
#define LED_DDR DDRB
|
||||||
|
#define LED_PORT PORTB
|
||||||
|
#define LED_NUM PORTB0
|
||||||
|
#define LED_POL 1
|
||||||
|
|
||||||
|
/* trim internal oscillator to get "good" baudrate */
|
||||||
|
#define OSCCAL_VALUE 0x80
|
||||||
|
|
||||||
|
/* *********************************************************************** */
|
||||||
|
#else
|
||||||
|
#error "unknown CONFIG"
|
||||||
|
#endif
|
||||||
|
/* *********************************************************************** */
|
||||||
|
|
||||||
|
/* needs F_CPU */
|
||||||
|
#include <util/delay.h>
|
||||||
|
|
||||||
|
#define UART_CALC_BAUDRATE(baudRate) ((uint32_t)(F_CPU) / ((uint32_t)(baudRate)*16) -1)
|
||||||
|
|
||||||
|
#if defined(ISP_NUM)
|
||||||
|
#if (ISP_POL == 0)
|
||||||
|
#define ISP_INIT() { ISP_DDR &= ~(1<<ISP_NUM); ISP_PORT |= (1<<ISP_NUM); }
|
||||||
|
#define ISP_CHECK() (ISP_PIN & (1<<ISP_NUM))
|
||||||
|
#else
|
||||||
|
#define ISP_INIT() { ISP_DDR &= ~(1<<ISP_NUM); ISP_PORT &= ~(1<<ISP_NUM); }
|
||||||
|
#define ISP_CHECK() !(ISP_PIN & (1<<ISP_NUM))
|
||||||
|
#endif
|
||||||
|
#endif /* defined(ISP_NUM) */
|
||||||
|
|
||||||
|
#if defined(LED_NUM)
|
||||||
|
#define LED_INIT() LED_DDR |= (1<<LED_NUM);
|
||||||
|
#if (LED_POL == 0)
|
||||||
|
#define LED_ON() LED_PORT &= ~(1<<LED_NUM)
|
||||||
|
#define LED_OFF() LED_PORT |= (1<<LED_NUM)
|
||||||
|
#else
|
||||||
|
#define LED_ON() LED_PORT |= (1<<LED_NUM)
|
||||||
|
#define LED_OFF() LED_PORT &= ~(1<<LED_NUM)
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define LED_INIT()
|
||||||
|
#define LED_ON()
|
||||||
|
#define LED_OFF()
|
||||||
|
#endif /* defined(LED_NUM) */
|
||||||
|
|
||||||
|
|
||||||
|
static uint8_t page_buf[SPM_PAGESIZE];
|
||||||
|
register uint16_t address asm("r2");
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__AVR_ATmega16__)
|
||||||
|
static void uartinit(void)
|
||||||
|
{
|
||||||
|
/* 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);
|
||||||
|
} /* uartinit */
|
||||||
|
|
||||||
|
static void sendchar(uint8_t data)
|
||||||
|
{
|
||||||
|
loop_until_bit_is_set(UCSRA, UDRE);
|
||||||
|
UDR = data;
|
||||||
|
} /* sendchar */
|
||||||
|
|
||||||
|
static uint8_t recvchar(void)
|
||||||
|
{
|
||||||
|
loop_until_bit_is_set(UCSRA, RXC);
|
||||||
|
return UDR;
|
||||||
|
} /* recvchar */
|
||||||
|
|
||||||
|
#if defined(TIMEOUT)
|
||||||
|
static uint8_t recvcheck(void)
|
||||||
|
{
|
||||||
|
return (UCSRA & (1<<RXC));
|
||||||
|
} /* recvcheck */
|
||||||
|
#endif /* defined(TIMEOUT) */
|
||||||
|
|
||||||
|
#elif defined(__AVR_ATmega88__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega644P__)
|
||||||
|
static void uartinit(void)
|
||||||
|
{
|
||||||
|
/* set baudrate */
|
||||||
|
UBRR0H = (UART_CALC_BAUDRATE(BAUDRATE)>>8) & 0xFF;
|
||||||
|
UBRR0L = (UART_CALC_BAUDRATE(BAUDRATE) & 0xFF);
|
||||||
|
|
||||||
|
/* USART: rx/tx enable, 8n1 */
|
||||||
|
UCSR0B = (1<<TXEN0) | (1<<RXEN0);
|
||||||
|
UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);
|
||||||
|
} /* uartinit */
|
||||||
|
|
||||||
|
static void sendchar(uint8_t data)
|
||||||
|
{
|
||||||
|
loop_until_bit_is_set(UCSR0A, UDRE0);
|
||||||
|
UDR0 = data;
|
||||||
|
} /* sendchar */
|
||||||
|
|
||||||
|
static uint8_t recvchar(void)
|
||||||
|
{
|
||||||
|
loop_until_bit_is_set(UCSR0A, RXC0);
|
||||||
|
return UDR0;
|
||||||
|
} /* recvchar */
|
||||||
|
|
||||||
|
#if defined(TIMEOUT)
|
||||||
|
static uint8_t recvcheck(void)
|
||||||
|
{
|
||||||
|
return (UCSR0A & (1<<RXC0));
|
||||||
|
} /* recvcheck */
|
||||||
|
#endif /* defined(TIMEOUT) */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static void eraseFlash(void)
|
||||||
|
{
|
||||||
|
address = 0;
|
||||||
|
while (address < BOOTLOADER_START) {
|
||||||
|
boot_page_erase(address);
|
||||||
|
boot_spm_busy_wait();
|
||||||
|
address += SPM_PAGESIZE;
|
||||||
|
}
|
||||||
|
boot_rww_enable();
|
||||||
|
} /* eraseFlash */
|
||||||
|
|
||||||
|
|
||||||
|
static void writeFlashPage(uint16_t size)
|
||||||
|
{
|
||||||
|
uint16_t pagestart = address;
|
||||||
|
uint8_t *tmp = page_buf;
|
||||||
|
|
||||||
|
do {
|
||||||
|
uint16_t data;
|
||||||
|
data = *tmp++;
|
||||||
|
data |= (*tmp++ << 8);
|
||||||
|
boot_page_fill(address, data);
|
||||||
|
|
||||||
|
address += 2;
|
||||||
|
size -= 2;
|
||||||
|
} while (size);
|
||||||
|
|
||||||
|
boot_page_write(pagestart);
|
||||||
|
boot_spm_busy_wait();
|
||||||
|
boot_rww_enable();
|
||||||
|
} /* writeFlashPage */
|
||||||
|
|
||||||
|
|
||||||
|
static void writeEEpromPage(uint16_t size)
|
||||||
|
{
|
||||||
|
uint8_t *tmp = page_buf;
|
||||||
|
|
||||||
|
do {
|
||||||
|
EEARL = address;
|
||||||
|
EEARH = (address >> 8);
|
||||||
|
EEDR = *tmp++;
|
||||||
|
address++;
|
||||||
|
|
||||||
|
#if defined(__AVR_ATmega16__)
|
||||||
|
EECR |= (1<<EEMWE);
|
||||||
|
EECR |= (1<<EEWE);
|
||||||
|
#elif defined(__AVR_ATmega88__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega644P__)
|
||||||
|
EECR |= (1<<EEMPE);
|
||||||
|
EECR |= (1<<EEPE);
|
||||||
|
#else
|
||||||
|
#error writeEEpromPage() not implemented
|
||||||
|
#endif
|
||||||
|
eeprom_busy_wait();
|
||||||
|
|
||||||
|
size--;
|
||||||
|
} while (size);
|
||||||
|
} /* writeEEpromPage */
|
||||||
|
|
||||||
|
|
||||||
|
static void readSendFlashPage(uint16_t size)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
sendchar(pgm_read_byte_near(address++));
|
||||||
|
size--;
|
||||||
|
} while (size);
|
||||||
|
} /* readSendFlashPage */
|
||||||
|
|
||||||
|
|
||||||
|
static void readSendEEpromPage(uint16_t size)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
EEARL = address;
|
||||||
|
EEARH = (address >> 8);
|
||||||
|
EECR |= (1<<EERE);
|
||||||
|
address++;
|
||||||
|
|
||||||
|
sendchar(EEDR);
|
||||||
|
|
||||||
|
size--;
|
||||||
|
} while (size);
|
||||||
|
} /* readSendEEpromPage */
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__AVR_ATmega88__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega644P__)
|
||||||
|
/*
|
||||||
|
* For newer devices the watchdog timer remains active even after a
|
||||||
|
* system reset. So disable it as soon as possible.
|
||||||
|
* automagically called on startup
|
||||||
|
*/
|
||||||
|
void disable_wdt_timer(void) __attribute__((naked, section(".init3")));
|
||||||
|
void disable_wdt_timer(void)
|
||||||
|
{
|
||||||
|
MCUSR = 0;
|
||||||
|
WDTCSR = (1<<WDCE) | (1<<WDE);
|
||||||
|
WDTCSR = (0<<WDE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void (*jump_to_app)(void) __attribute__ ((noreturn)) = 0x0000;
|
||||||
|
|
||||||
|
int main(void) __attribute__ ((noreturn));
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
#if defined(ISP_NUM)
|
||||||
|
/* set as input, enable pullup/pulldown */
|
||||||
|
ISP_INIT();
|
||||||
|
|
||||||
|
/* check if bootloader is not selected */
|
||||||
|
if (ISP_CHECK()) {
|
||||||
|
jump_to_app();
|
||||||
|
}
|
||||||
|
#endif /* defined(ISP_NUM) */
|
||||||
|
|
||||||
|
#if defined(LED_NUM)
|
||||||
|
LED_DDR |= (1<<LED_NUM);
|
||||||
|
#endif /* defined(LED_NUM) */
|
||||||
|
|
||||||
|
#if defined(OSCCAL_VALUE)
|
||||||
|
OSCCAL = OSCCAL_VALUE;
|
||||||
|
#endif /* defined(OSCCAL_VALUE) */
|
||||||
|
|
||||||
|
/* initalize UART */
|
||||||
|
uartinit();
|
||||||
|
|
||||||
|
uint8_t val = 'S';
|
||||||
|
|
||||||
|
#if defined(TIMEOUT)
|
||||||
|
uint8_t prev = 0x00;
|
||||||
|
uint8_t boot_timeout = TIMEOUT;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (recvcheck()) {
|
||||||
|
val = recvchar();
|
||||||
|
|
||||||
|
#if defined(SUPPORT_MKBL)
|
||||||
|
if ((prev == 0x1B) && (val == 0xAA || val == 'S')) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if ((prev == 0x1B) && (val == 'S')) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif /* defined(SUPPORT_MKBL) */
|
||||||
|
|
||||||
|
prev = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
_delay_ms(10);
|
||||||
|
|
||||||
|
boot_timeout--;
|
||||||
|
if (boot_timeout == 0x00) {
|
||||||
|
LED_OFF();
|
||||||
|
jump_to_app();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(LED_NUM)
|
||||||
|
if (!(boot_timeout & 0x03)) {
|
||||||
|
LED_PORT ^= (1<<LED_NUM);
|
||||||
|
}
|
||||||
|
#endif /* defined(LED_NUM) */
|
||||||
|
}
|
||||||
|
#endif /* defined(TIMEOUT) */
|
||||||
|
|
||||||
|
/* turn on LED */
|
||||||
|
LED_ON();
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
uint8_t response = 0xFF;
|
||||||
|
|
||||||
|
/* Autoincrement? */
|
||||||
|
if (val == 'a') {
|
||||||
|
response = 'Y';
|
||||||
|
|
||||||
|
/* write address */
|
||||||
|
} else if (val == 'A') {
|
||||||
|
address = (recvchar() << 8);
|
||||||
|
address |= recvchar();
|
||||||
|
response = '\r';
|
||||||
|
|
||||||
|
/* Buffer load support */
|
||||||
|
} else if (val == 'b') {
|
||||||
|
sendchar('Y');
|
||||||
|
sendchar((SPM_PAGESIZE >> 8) & 0xFF);
|
||||||
|
response = SPM_PAGESIZE & 0xFF;
|
||||||
|
|
||||||
|
/* Start buffer load */
|
||||||
|
} else if (val == 'B') {
|
||||||
|
uint16_t size;
|
||||||
|
uint16_t count;
|
||||||
|
uint8_t *data = page_buf;
|
||||||
|
|
||||||
|
size = (recvchar() << 8);
|
||||||
|
size |= recvchar();
|
||||||
|
val = recvchar();
|
||||||
|
|
||||||
|
for (count = 0; count < SPM_PAGESIZE; count++) {
|
||||||
|
*data++ = (count < size) ? recvchar() : 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((val == 'F') && (address < BOOTLOADER_START)) {
|
||||||
|
writeFlashPage(size);
|
||||||
|
response = '\r';
|
||||||
|
|
||||||
|
} else if ((val == 'E') && (address < E2END)) {
|
||||||
|
writeEEpromPage(size);
|
||||||
|
response = '\r';
|
||||||
|
|
||||||
|
} else {
|
||||||
|
response = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Block read */
|
||||||
|
} else if (val == 'g') {
|
||||||
|
uint16_t size;
|
||||||
|
|
||||||
|
size = (recvchar() << 8);
|
||||||
|
size |= recvchar();
|
||||||
|
val = recvchar();
|
||||||
|
|
||||||
|
if (val == 'F') {
|
||||||
|
readSendFlashPage(size);
|
||||||
|
|
||||||
|
} else if (val == 'E') {
|
||||||
|
readSendEEpromPage(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Chip erase */
|
||||||
|
} else if (val == 'e') {
|
||||||
|
eraseFlash();
|
||||||
|
response = '\r';
|
||||||
|
|
||||||
|
/* Exit upgrade */
|
||||||
|
} else if (val == 'E') {
|
||||||
|
wdt_enable(WDTO_250MS);
|
||||||
|
response = '\r';
|
||||||
|
|
||||||
|
/* Enter/Leave programming mode */
|
||||||
|
} else if ((val == 'P') || (val == 'L')) {
|
||||||
|
response = '\r';
|
||||||
|
|
||||||
|
/* return programmer type: serial */
|
||||||
|
} else if (val == 'p') {
|
||||||
|
response = 'S';
|
||||||
|
|
||||||
|
/* Return device type */
|
||||||
|
} else if (val == 't') {
|
||||||
|
sendchar(DEVCODE);
|
||||||
|
response = 0x00;
|
||||||
|
|
||||||
|
/* Clear and set LED ignored */
|
||||||
|
} else if ((val == 'x') || (val == 'y')) {
|
||||||
|
recvchar();
|
||||||
|
response = '\r';
|
||||||
|
|
||||||
|
/* Set device */
|
||||||
|
} else if (val == 'T') {
|
||||||
|
response = (recvchar() == DEVCODE) ? '\r' : 0x00;
|
||||||
|
|
||||||
|
/* Return software identifier */
|
||||||
|
} else if (val == 'S') {
|
||||||
|
sendchar('A');
|
||||||
|
sendchar('V');
|
||||||
|
sendchar('R');
|
||||||
|
sendchar('B');
|
||||||
|
sendchar('O');
|
||||||
|
sendchar('O');
|
||||||
|
response = 'T';
|
||||||
|
|
||||||
|
#if defined(SUPPORT_MKBL)
|
||||||
|
} else if (val == 0xAA) {
|
||||||
|
sendchar('M');
|
||||||
|
sendchar('K');
|
||||||
|
sendchar('B');
|
||||||
|
response = 'L';
|
||||||
|
#endif /* defined(SUPPORT_MKBL) */
|
||||||
|
|
||||||
|
/* Return Software/Hardware Version */
|
||||||
|
} else if ((val == 'V') || (val == 'v')) {
|
||||||
|
sendchar('0');
|
||||||
|
response = '8';
|
||||||
|
|
||||||
|
/* Return Signature Bytes */
|
||||||
|
} else if (val == 's') {
|
||||||
|
sendchar(SIGNATURE_2);
|
||||||
|
sendchar(SIGNATURE_1);
|
||||||
|
response = SIGNATURE_0;
|
||||||
|
|
||||||
|
} else if (val != 0x1B) {
|
||||||
|
response = '?';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response != 0xFF) {
|
||||||
|
sendchar(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
val = recvchar();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user