From 125bdc17291a20e8d55825e8dc30fb44574616ab Mon Sep 17 00:00:00 2001 From: Olaf Rempel Date: Sun, 5 Jun 2011 14:39:59 +0200 Subject: [PATCH] reduce sizae and compat work - current firmware need more space -> reduce bootloader size from 4K => 2K - remove timer ISR - remove interrupt vectors from linked binary - make avr910 bootloader entry command more robust (old: 'S', new: { 0x1B, 'S'} ) - add compat bootloader entry command (rx: { 0x1B, 0xAA } -> tx: 'MKBL') - do not leave bootloader after upgrading twiboot slave - do not erase local flash when upgrading twiboot slave - remove readable chipinfo output from twiboot slaves --- .gitignore | 1 + Makefile | 18 ++- README | 25 ++++ main.c | 329 ++++++++++++++++++++--------------------------------- 4 files changed, 162 insertions(+), 211 deletions(-) create mode 100644 README diff --git a/.gitignore b/.gitignore index 6d36148..b775df2 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ *.hex *.lst *.map +ldscript-no-vectors.x diff --git a/Makefile b/Makefile index 3746230..6c091e7 100644 --- a/Makefile +++ b/Makefile @@ -6,23 +6,33 @@ OPTIMIZE = -Os DEFS = LIBS = +LDSCRIPT_SRC := /usr/lib/ldscripts/avr5.x +LDSCRIPT_DST := ldscript-no-vectors.x + # Override is only needed by avr-lib build system. override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS) -override LDFLAGS = -Wl,-Map,$(PRG).map,--section-start=.text=0xF000 +override LDFLAGS = -Wl,-Map,$(PRG).map,--section-start=.text=0xF800,-T$(LDSCRIPT_DST) CC = avr-gcc OBJCOPY = avr-objcopy OBJDUMP = avr-objdump SIZE = avr-size +#LDSCRIPT_SRC := $(shell LANG=C $(CC) $(CFLAGS) -Wl,--verbose 2> /dev/null | awk '/^opened script file (.*)$$/{ print $$4 }') + all: $(PRG).elf lst text $(SIZE) -x -A $(PRG).elf -$(PRG).elf: $(OBJ) +$(PRG).elf: $(OBJ) | $(LDSCRIPT_DST) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) +$(LDSCRIPT_DST): $(LDSCRIPT_SRC) +# remove all lines with *vectors* and insert DISCARD line above .text declaration + sed -e '/.*vectors.*/d' -e 's/\(^[ \t]*\)\(.text[ \t]*\:\)$$/\1\/DISCARD\/ : { *(.vectors) }\n\1\2/g' $^ > $@ +# -diff -uNr $^ $@ > $@.diff + clean: - rm -rf *.o $(PRG).lst $(PRG).map $(PRG).elf $(PRG).hex $(PRG).bin + rm -rf *.o $(PRG).lst $(PRG).map $(PRG).elf $(PRG).hex $(PRG).bin $(LDSCRIPT_DST) lst: $(PRG).lst @@ -41,4 +51,4 @@ bin: $(PRG).bin $(OBJCOPY) -j .text -j .data -O binary $< $@ install: text - avrdude -c dragon_isp -P usb -p m644p -B0.3 -V -U flash:w:$(PRG).hex + avrdude -c dragon_isp -P usb -p m644p -V -U flash:w:$(PRG).hex diff --git a/README b/README new file mode 100644 index 0000000..8702a5b --- /dev/null +++ b/README @@ -0,0 +1,25 @@ +1) Flash FC firmware: +# reset running firmware (MCU will execute bootloader only for ~1s!) +$ echo -e -n "#aR@S\r" > /dev/ttyUSB1 + +# flash new firmware +$ avrdude -p m644p -c butterfly -b 57600 -P /dev/ttyUSB1 -U flash:w:/tmp/Flight-Ctrl_MEGA644_V0_82a.hex + + +2) Flash BLMC firmware (via twiboot): +# enter bootloader (0x1B, 'S'), select first twi-slave ('1'): +$ echo -e -n "\x1BS1" > /dev/ttyUSB1 + +# flash new firmware +$ avrdude -p m8 -c butterfly -b 57600 -P /dev/ttyUSB1 -U flash:w:/tmp/blmc.hex + +# select next twi-slave (bootloader is still active) +$ echo -e -n "2" > /dev/ttyUSB1 + + +3) Other Commands: +'0' => select FC internal flash/eeprom +'1' - '4' => select twi-slave 1-4, print bootloader version +'I' => start application on selected twi-slave, print application version +'l' => start selected motor +'k' => stop selected motor diff --git a/main.c b/main.c index dfdca5e..f59a397 100644 --- a/main.c +++ b/main.c @@ -25,7 +25,7 @@ /* * ATMega 644P: * Fuse E: 0xFD (2.7V BOD) - * Fuse H: 0xDA (2048 words bootloader) + * Fuse H: 0xDC (1024 words bootloader) * Fuse L: 0xFF (ext. Crystal) */ @@ -35,15 +35,15 @@ #define BAUDRATE 57600 #define UART_CALC_BAUDRATE(baudRate) ((uint32_t)(F_CPU) / ((uint32_t)(baudRate)*16) -1) -#define APP_END 0xF000 +#define APP_END 0xF7FF #define LED_RT (1<> 4) & 0x0F; - sendchar((tmp < 0x0A) ? ('0' + tmp) : ('a' - 0x0A + tmp)); - - tmp = val & 0x0F; - sendchar((tmp < 0x0A) ? ('0' + tmp) : ('a' - 0x0A + tmp)); -} - -static uint8_t i2c_master_tx(uint8_t val) +static void i2c_master_tx(uint8_t val) { TWDR = val; TWCR = (1< 0) - boot_timeout--; + _delay_ms(20); } -static uint16_t address; -static uint16_t page_size; -static uint8_t page_buf[SPM_PAGESIZE]; +static void i2c_print_version(uint8_t i2c_dev) +{ + i2c_start_address(i2c_dev); + i2c_master_tx(CMD_READ_VERSION); + i2c_start_address(i2c_dev | 0x01); + uint8_t cnt = 16; + while (cnt--) { + sendchar(i2c_master_rx(cnt)); + } + + i2c_stop(); +} + +static uint8_t page_buf[SPM_PAGESIZE]; static void eraseFlash(void) { - uint32_t addr = 0; - while (APP_END > addr) { - boot_page_erase(addr); + uint16_t address = 0; + while (APP_END < address) { + boot_page_erase(address); boot_spm_busy_wait(); - addr += SPM_PAGESIZE; + address += SPM_PAGESIZE; } boot_rww_enable(); } -static uint16_t writeFlashPage(uint16_t waddr, uint16_t size) +static void writeFlashPage(uint16_t address, uint16_t size) { - uint32_t pagestart = (uint32_t)waddr<<1; - uint32_t baddr = pagestart; + uint16_t pagestart = address; uint16_t data; uint8_t *tmp = page_buf; do { data = *tmp++; data |= *tmp++ << 8; - boot_page_fill(baddr, data); + boot_page_fill(address, data); - baddr += 2; + address += 2; size -= 2; } while (size); boot_page_write(pagestart); boot_spm_busy_wait(); boot_rww_enable(); - - return baddr>>1; } -static uint16_t writeEEpromPage(uint16_t address, uint16_t size) +static void writeEEpromPage(uint16_t address, uint16_t size) { uint8_t *tmp = page_buf; @@ -209,31 +193,22 @@ static uint16_t writeEEpromPage(uint16_t address, uint16_t size) size--; } while (size); - - return address; } -static uint16_t readFlashPage(uint16_t waddr, uint16_t size) +static void readFlashPage(uint16_t address, uint16_t size) { - uint32_t baddr = (uint32_t)waddr<<1; uint16_t data; do { -#if defined(RAMPZ) - data = pgm_read_word_far(baddr); -#else - data = pgm_read_word_near(baddr); -#endif + data = pgm_read_word_near(address); sendchar(data); sendchar((data >> 8)); - baddr += 2; + address += 2; size -= 2; } while (size); - - return baddr>>1; } -static uint16_t readEEpromPage(uint16_t address, uint16_t size) +static void readEEpromPage(uint16_t address, uint16_t size) { do { EEARL = address; @@ -245,43 +220,36 @@ static uint16_t readEEpromPage(uint16_t address, uint16_t size) size--; } while (size); - - return address; } /* 0-2: signature, 3: pagesize, 4-5: flash size, 6-7: eeprom size */ static uint8_t chipinfo[8]; -void cmd_loop(void) +void cmd_loop(uint8_t val) { + uint16_t address = 0; + uint16_t page_size = 0; uint8_t i2c_dev = 0; - sendchar('F'); - sendchar('C'); - sendchar('_'); - sendchar('B'); - sendchar('O'); - sendchar('O'); - sendchar('T'); - while (1) { - uint8_t val = recvchar(); + uint8_t response = 0xFF; + // Autoincrement? if (val == 'a') { - sendchar('Y'); + response = 'Y'; // write address } else if (val == 'A') { address = recvchar(); address = (address << 8) | recvchar(); - sendchar('\r'); + response = '\r'; // Buffer load support } else if (val == 'b') { sendchar('Y'); page_size = (i2c_dev == 0) ? sizeof(page_buf) : chipinfo[3]; sendchar((page_size >> 8) & 0xFF); - sendchar(page_size & 0xFF); + response = page_size & 0Xff; // Start buffer load } else if (val == 'B') { @@ -313,12 +281,13 @@ void cmd_loop(void) } else { if (val == 'F') { - address = writeFlashPage(address, size); + writeFlashPage(address, size); } else if (val == 'E') { - address = writeEEpromPage(address, size); + writeEEpromPage(address, size); } + address += size; } - sendchar('\r'); + response = '\r'; // Block read } else if (val == 'g') { @@ -335,8 +304,7 @@ void cmd_loop(void) i2c_start_address(i2c_dev | 0x01); while (size--) { - i2c_master_rx(&val, size > 0); - sendchar(val); + sendchar(i2c_master_rx(size > 0)); address++; } @@ -344,64 +312,48 @@ void cmd_loop(void) } else { if (val == 'F') { - address = readFlashPage(address, size); + readFlashPage(address, size); } else if (val == 'E') { - address = readEEpromPage(address, size); + readEEpromPage(address, size); } + address += size; } // Chip erase } else if (val == 'e') { - eraseFlash(); - sendchar('\r'); + if (i2c_dev == 0) { + eraseFlash(); + } + response = '\r'; // Exit upgrade } else if (val == 'E') { - boot_timeout = 0; sendchar('\r'); - _delay_ms(10); - break; - - // Enter programming mode - } else if (val == 'P') { - if (i2c_dev != 0) { - i2c_start_address(i2c_dev); - i2c_master_tx(CMD_SWITCH_APPLICATION); - i2c_master_tx(BOOTTYPE_BOOTLOADER); - i2c_stop(); - - _delay_ms(10); + if (i2c_dev == 0) { + return; } - sendchar('\r'); - // Leave programming mode - } else if (val == 'L') { + // Enter / Leave programming mode + } else if (val == 'P' || val == 'L') { if (i2c_dev != 0) { - i2c_start_address(i2c_dev); - i2c_master_tx(CMD_SWITCH_APPLICATION); - i2c_master_tx(BOOTTYPE_APPLICATION); - i2c_stop(); + val = (val == 'P') ? BOOTTYPE_BOOTLOADER : BOOTTYPE_APPLICATION; + i2c_switch_app(i2c_dev, val); } - sendchar('\r'); + response = '\r'; // return programmer type } else if (val == 'p') { - sendchar('S'); + response = 'S'; // Return device type } else if (val == 't') { sendchar((i2c_dev == 0) ? OWN_DEVCODE : TWI_DEVCODE); - sendchar(0); + response = '\0'; // clear and set LED ignored - } else if ((val == 'x') || (val == 'y')) { + } else if ((val == 'x') || (val == 'y') || (val == 'T')) { recvchar(); - sendchar('\r'); - - // set device - } else if (val == 'T') { - recvchar(); - sendchar('\r'); + response = '\r'; // Return software identifier } else if (val == 'S') { @@ -411,58 +363,37 @@ void cmd_loop(void) sendchar('B'); sendchar('O'); sendchar('O'); - sendchar('T'); + response = 'T'; // Return Software Version } else if (val == 'V' || val == 'v') { sendchar('0'); - sendchar('8'); + response = '8'; // Return Signature Bytes } else if (val == 's') { if (i2c_dev != 0) { sendchar(chipinfo[2]); sendchar(chipinfo[1]); - sendchar(chipinfo[0]); + response = chipinfo[0]; } else { uint8_t sig[3] = OWN_SIGNATURE; sendchar(sig[2]); sendchar(sig[1]); - sendchar(sig[0]); + response = sig[0]; } // set i2c target } else if (val == '0') { i2c_dev = 0; - sendchar(val); } else if (val >= '1' && val <= '4') { i2c_dev = (val - '0' + TWI_ADDRESS_BASE) << 1; - sendchar(val); - sendchar('<'); - i2c_start_address(i2c_dev); - i2c_master_tx(CMD_SWITCH_APPLICATION); - i2c_master_tx(BOOTTYPE_BOOTLOADER); - i2c_stop(); - - for (val = 0; val < 10; val++) - _delay_ms(10); - - i2c_start_address(i2c_dev); - i2c_master_tx(CMD_READ_VERSION); - i2c_start_address(i2c_dev | 0x01); - - uint8_t cnt; - for (cnt = 0; cnt < 16; cnt++) { - i2c_master_rx(&val, (cnt != 15)); - sendchar(val); - } - - i2c_stop(); - - sendchar(','); + i2c_switch_app(i2c_dev, BOOTTYPE_BOOTLOADER); + _delay_ms(100); + i2c_print_version(i2c_dev); i2c_start_address(i2c_dev); i2c_master_tx(CMD_READ_MEMORY); @@ -474,12 +405,7 @@ void cmd_loop(void) uint8_t i; for (i = 0; i < sizeof(chipinfo); i++) { uint8_t more = (i < (sizeof(chipinfo) -1)); - i2c_master_rx(&chipinfo[i], more); - - sendchar('0'); - sendchar('x'); - print_byte(chipinfo[i]); - sendchar(more ? ',' : '>'); + chipinfo[i] = i2c_master_rx(more); } i2c_stop(); @@ -489,39 +415,34 @@ void cmd_loop(void) i2c_start_address(i2c_dev); i2c_master_tx(0x00 + (val - 'k') * 0x10); i2c_stop(); - - sendchar(val); + response = val; } - // start Application / get Version + // get Version } else if (val == 'I') { if (i2c_dev != 0) { - i2c_start_address(i2c_dev); - i2c_master_tx(CMD_SWITCH_APPLICATION); - i2c_master_tx(BOOTTYPE_APPLICATION); - i2c_stop(); - - for (val = 0; val < 10; val++) - _delay_ms(10); - - i2c_start_address(i2c_dev); - i2c_master_tx(CMD_READ_VERSION); - i2c_start_address(i2c_dev | 0x01); - - sendchar('<'); - uint8_t cnt; - for (cnt = 0; cnt < 16; cnt++) { - i2c_master_rx(&val, (cnt != 15)); - sendchar(val); - } - sendchar('>'); - i2c_stop(); + i2c_switch_app(i2c_dev, BOOTTYPE_APPLICATION); + _delay_ms(100); + i2c_print_version(i2c_dev); } + // fake MK-TOOL specific stuff + } else if (val == 0xAA) { + sendchar('M'); + sendchar('K'); + sendchar('B'); + response = 'L'; + /* ESC */ } else if (val != 0x1b) { - sendchar('?'); + response = '?'; } + + if (response != 0xFF) { + sendchar(response); + } + + val = recvchar(); } } @@ -532,7 +453,6 @@ static void (*jump_to_app)(void) __attribute__ ((noreturn)) = 0x0000; * system reset. So disable it as soon as possible. * automagically called on startup */ -#if defined (__AVR_ATmega88__) || defined (__AVR_ATmega168__) void disable_wdt_timer(void) __attribute__((naked, section(".init3"))); void disable_wdt_timer(void) { @@ -540,17 +460,15 @@ void disable_wdt_timer(void) WDTCSR = (1<>8) & 0xFF; @@ -560,35 +478,32 @@ int main(void) UCSR0B = (1< 0) { - if (UCSR0A & (1< 0) { + if (UCSR0A & (1<