From e7b67a0aa78ad956ba29948317daa1a9a8fd18cb Mon Sep 17 00:00:00 2001 From: Olaf Rempel Date: Mon, 6 Oct 2014 22:18:42 +0200 Subject: [PATCH] initial version --- .gitignore | 8 + Makefile | 104 ++++++++++ main.c | 544 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 656 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 main.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b28a635 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +*.o +*.elf +*.bin +*.hex +*.lst +*.lss +*.map +ldscript-no-vectors-*.x diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6f9d9e2 --- /dev/null +++ b/Makefile @@ -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)) diff --git a/main.c b/main.c new file mode 100644 index 0000000..2da6fa3 --- /dev/null +++ b/main.c @@ -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 +#include +#include +#include +#include + +/* *********************************************************************** */ +#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 + +#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<>8) & 0xFF; + UBRRL = (UART_CALC_BAUDRATE(BAUDRATE) & 0xFF); + + /* enable usart with 8n1 */ + UCSRB = (1<>8) & 0xFF; + UBRR0L = (UART_CALC_BAUDRATE(BAUDRATE) & 0xFF); + + /* USART: rx/tx enable, 8n1 */ + UCSR0B = (1<> 8); + EEDR = *tmp++; + address++; + +#if defined(__AVR_ATmega16__) + EECR |= (1<> 8); + EECR |= (1<> 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(); + } +}