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
This commit is contained in:
Olaf Rempel 2011-06-05 14:39:59 +02:00
parent a7fcfaf7b9
commit 125bdc1729
4 changed files with 162 additions and 211 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@
*.hex *.hex
*.lst *.lst
*.map *.map
ldscript-no-vectors.x

View File

@ -6,23 +6,33 @@ OPTIMIZE = -Os
DEFS = DEFS =
LIBS = LIBS =
LDSCRIPT_SRC := /usr/lib/ldscripts/avr5.x
LDSCRIPT_DST := ldscript-no-vectors.x
# Override is only needed by avr-lib build system. # Override is only needed by avr-lib build system.
override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS) 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 CC = avr-gcc
OBJCOPY = avr-objcopy OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump OBJDUMP = avr-objdump
SIZE = avr-size 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 all: $(PRG).elf lst text
$(SIZE) -x -A $(PRG).elf $(SIZE) -x -A $(PRG).elf
$(PRG).elf: $(OBJ) $(PRG).elf: $(OBJ) | $(LDSCRIPT_DST)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) $(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: 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 lst: $(PRG).lst
@ -41,4 +51,4 @@ bin: $(PRG).bin
$(OBJCOPY) -j .text -j .data -O binary $< $@ $(OBJCOPY) -j .text -j .data -O binary $< $@
install: text 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

25
README Normal file
View File

@ -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

329
main.c
View File

@ -25,7 +25,7 @@
/* /*
* ATMega 644P: * ATMega 644P:
* Fuse E: 0xFD (2.7V BOD) * Fuse E: 0xFD (2.7V BOD)
* Fuse H: 0xDA (2048 words bootloader) * Fuse H: 0xDC (1024 words bootloader)
* Fuse L: 0xFF (ext. Crystal) * Fuse L: 0xFF (ext. Crystal)
*/ */
@ -35,15 +35,15 @@
#define BAUDRATE 57600 #define BAUDRATE 57600
#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 APP_END 0xF000 #define APP_END 0xF7FF
#define LED_RT (1<<PORTB0) /* low active */ #define LED_RT (1<<PORTB0) /* low active */
#define LED_GN (1<<PORTB1) /* high active */ #define LED_GN (1<<PORTB1) /* high active */
#define TWI_CLK 100000 #define TWI_CLK 100000
#define TWI_ADDRESS_BASE 0x20 /* 0x21 - 0x24 */ #define TWI_ADDRESS_BASE 0x28 /* 0x29 - 0x2C */
#define TWI_DEVCODE 0x77 /* Mega8 */ #define TWI_DEVCODE 0x76 /* Mega8 */
#define OWN_DEVCODE 0x74 /* Mega644 */ #define OWN_DEVCODE 0x74 /* Mega644 */
#define OWN_SIGNATURE { 0x1E, 0x96, 0x0A } /* Mega644P */ #define OWN_SIGNATURE { 0x1E, 0x96, 0x0A } /* Mega644P */
@ -79,26 +79,14 @@ static uint8_t recvchar(void)
return UDR0; return UDR0;
} }
static void print_byte(uint8_t val) static void i2c_master_tx(uint8_t val)
{
uint8_t tmp = (val >> 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)
{ {
TWDR = val; TWDR = val;
TWCR = (1<<TWINT) | (1<<TWEN); TWCR = (1<<TWINT) | (1<<TWEN);
loop_until_bit_is_set(TWCR, TWINT); loop_until_bit_is_set(TWCR, TWINT);
uint8_t status = TWSR & 0xF8;
return status;
} }
static uint8_t i2c_master_rx(uint8_t *val, uint8_t ack) static uint8_t i2c_master_rx(uint8_t ack)
{ {
if (ack) if (ack)
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA); TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
@ -106,10 +94,7 @@ static uint8_t i2c_master_rx(uint8_t *val, uint8_t ack)
TWCR = (1<<TWINT) | (1<<TWEN); TWCR = (1<<TWINT) | (1<<TWEN);
loop_until_bit_is_set(TWCR, TWINT); loop_until_bit_is_set(TWCR, TWINT);
*val = TWDR; return TWDR;
uint8_t status = TWSR & 0xF8;
return status;
} }
static void i2c_stop(void) static void i2c_stop(void)
@ -125,7 +110,8 @@ static void i2c_start_address(uint8_t addr)
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
loop_until_bit_is_set(TWCR, TWINT); loop_until_bit_is_set(TWCR, TWINT);
uint8_t status = i2c_master_tx(addr); i2c_master_tx(addr);
uint8_t status = (TWSR & 0xF8);
if (status == 0x18 || status == 0x40) if (status == 0x18 || status == 0x40)
break; break;
@ -134,66 +120,64 @@ static void i2c_start_address(uint8_t addr)
} }
} }
/* wait 100x 10ms */ static void i2c_switch_app(uint8_t i2c_dev, uint8_t app)
volatile static uint8_t boot_timeout = 100;
ISR(TIMER0_OVF_vect)
{ {
static uint8_t cnt; i2c_start_address(i2c_dev);
i2c_master_tx(CMD_SWITCH_APPLICATION);
i2c_master_tx(app);
i2c_stop();
/* come back in 10ms (@20MHz) */ _delay_ms(20);
TCNT0 = 0xFF - 195;
/* blink LED while running */
cnt++;
cnt &= 0x03;
if (cnt == 0x00)
PORTB ^= LED_GN;
if (boot_timeout > 0)
boot_timeout--;
} }
static uint16_t address; static void i2c_print_version(uint8_t i2c_dev)
static uint16_t page_size; {
static uint8_t page_buf[SPM_PAGESIZE]; 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) static void eraseFlash(void)
{ {
uint32_t addr = 0; uint16_t address = 0;
while (APP_END > addr) { while (APP_END < address) {
boot_page_erase(addr); boot_page_erase(address);
boot_spm_busy_wait(); boot_spm_busy_wait();
addr += SPM_PAGESIZE; address += SPM_PAGESIZE;
} }
boot_rww_enable(); 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; uint16_t pagestart = address;
uint32_t baddr = pagestart;
uint16_t data; uint16_t data;
uint8_t *tmp = page_buf; uint8_t *tmp = page_buf;
do { do {
data = *tmp++; data = *tmp++;
data |= *tmp++ << 8; data |= *tmp++ << 8;
boot_page_fill(baddr, data); boot_page_fill(address, data);
baddr += 2; address += 2;
size -= 2; size -= 2;
} while (size); } while (size);
boot_page_write(pagestart); boot_page_write(pagestart);
boot_spm_busy_wait(); boot_spm_busy_wait();
boot_rww_enable(); 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; uint8_t *tmp = page_buf;
@ -209,31 +193,22 @@ static uint16_t writeEEpromPage(uint16_t address, uint16_t size)
size--; size--;
} while (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; uint16_t data;
do { do {
#if defined(RAMPZ) data = pgm_read_word_near(address);
data = pgm_read_word_far(baddr);
#else
data = pgm_read_word_near(baddr);
#endif
sendchar(data); sendchar(data);
sendchar((data >> 8)); sendchar((data >> 8));
baddr += 2; address += 2;
size -= 2; size -= 2;
} while (size); } 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 { do {
EEARL = address; EEARL = address;
@ -245,43 +220,36 @@ static uint16_t readEEpromPage(uint16_t address, uint16_t size)
size--; size--;
} while (size); } while (size);
return address;
} }
/* 0-2: signature, 3: pagesize, 4-5: flash size, 6-7: eeprom size */ /* 0-2: signature, 3: pagesize, 4-5: flash size, 6-7: eeprom size */
static uint8_t chipinfo[8]; 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; uint8_t i2c_dev = 0;
sendchar('F');
sendchar('C');
sendchar('_');
sendchar('B');
sendchar('O');
sendchar('O');
sendchar('T');
while (1) { while (1) {
uint8_t val = recvchar(); uint8_t response = 0xFF;
// Autoincrement? // Autoincrement?
if (val == 'a') { if (val == 'a') {
sendchar('Y'); response = 'Y';
// write address // write address
} else if (val == 'A') { } else if (val == 'A') {
address = recvchar(); address = recvchar();
address = (address << 8) | recvchar(); address = (address << 8) | recvchar();
sendchar('\r'); response = '\r';
// Buffer load support // Buffer load support
} else if (val == 'b') { } else if (val == 'b') {
sendchar('Y'); sendchar('Y');
page_size = (i2c_dev == 0) ? sizeof(page_buf) : chipinfo[3]; page_size = (i2c_dev == 0) ? sizeof(page_buf) : chipinfo[3];
sendchar((page_size >> 8) & 0xFF); sendchar((page_size >> 8) & 0xFF);
sendchar(page_size & 0xFF); response = page_size & 0Xff;
// Start buffer load // Start buffer load
} else if (val == 'B') { } else if (val == 'B') {
@ -313,12 +281,13 @@ void cmd_loop(void)
} else { } else {
if (val == 'F') { if (val == 'F') {
address = writeFlashPage(address, size); writeFlashPage(address, size);
} else if (val == 'E') { } else if (val == 'E') {
address = writeEEpromPage(address, size); writeEEpromPage(address, size);
} }
address += size;
} }
sendchar('\r'); response = '\r';
// Block read // Block read
} else if (val == 'g') { } else if (val == 'g') {
@ -335,8 +304,7 @@ void cmd_loop(void)
i2c_start_address(i2c_dev | 0x01); i2c_start_address(i2c_dev | 0x01);
while (size--) { while (size--) {
i2c_master_rx(&val, size > 0); sendchar(i2c_master_rx(size > 0));
sendchar(val);
address++; address++;
} }
@ -344,64 +312,48 @@ void cmd_loop(void)
} else { } else {
if (val == 'F') { if (val == 'F') {
address = readFlashPage(address, size); readFlashPage(address, size);
} else if (val == 'E') { } else if (val == 'E') {
address = readEEpromPage(address, size); readEEpromPage(address, size);
} }
address += size;
} }
// Chip erase // Chip erase
} else if (val == 'e') { } else if (val == 'e') {
eraseFlash(); if (i2c_dev == 0) {
sendchar('\r'); eraseFlash();
}
response = '\r';
// Exit upgrade // Exit upgrade
} else if (val == 'E') { } else if (val == 'E') {
boot_timeout = 0;
sendchar('\r'); sendchar('\r');
_delay_ms(10); if (i2c_dev == 0) {
break; return;
// 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);
} }
sendchar('\r');
// Leave programming mode // Enter / Leave programming mode
} else if (val == 'L') { } else if (val == 'P' || val == 'L') {
if (i2c_dev != 0) { if (i2c_dev != 0) {
i2c_start_address(i2c_dev); val = (val == 'P') ? BOOTTYPE_BOOTLOADER : BOOTTYPE_APPLICATION;
i2c_master_tx(CMD_SWITCH_APPLICATION); i2c_switch_app(i2c_dev, val);
i2c_master_tx(BOOTTYPE_APPLICATION);
i2c_stop();
} }
sendchar('\r'); response = '\r';
// return programmer type // return programmer type
} else if (val == 'p') { } else if (val == 'p') {
sendchar('S'); response = 'S';
// Return device type // Return device type
} else if (val == 't') { } else if (val == 't') {
sendchar((i2c_dev == 0) ? OWN_DEVCODE : TWI_DEVCODE); sendchar((i2c_dev == 0) ? OWN_DEVCODE : TWI_DEVCODE);
sendchar(0); response = '\0';
// clear and set LED ignored // clear and set LED ignored
} else if ((val == 'x') || (val == 'y')) { } else if ((val == 'x') || (val == 'y') || (val == 'T')) {
recvchar(); recvchar();
sendchar('\r'); response = '\r';
// set device
} else if (val == 'T') {
recvchar();
sendchar('\r');
// Return software identifier // Return software identifier
} else if (val == 'S') { } else if (val == 'S') {
@ -411,58 +363,37 @@ void cmd_loop(void)
sendchar('B'); sendchar('B');
sendchar('O'); sendchar('O');
sendchar('O'); sendchar('O');
sendchar('T'); response = 'T';
// Return Software Version // Return Software Version
} else if (val == 'V' || val == 'v') { } else if (val == 'V' || val == 'v') {
sendchar('0'); sendchar('0');
sendchar('8'); response = '8';
// Return Signature Bytes // Return Signature Bytes
} else if (val == 's') { } else if (val == 's') {
if (i2c_dev != 0) { if (i2c_dev != 0) {
sendchar(chipinfo[2]); sendchar(chipinfo[2]);
sendchar(chipinfo[1]); sendchar(chipinfo[1]);
sendchar(chipinfo[0]); response = chipinfo[0];
} else { } else {
uint8_t sig[3] = OWN_SIGNATURE; uint8_t sig[3] = OWN_SIGNATURE;
sendchar(sig[2]); sendchar(sig[2]);
sendchar(sig[1]); sendchar(sig[1]);
sendchar(sig[0]); response = sig[0];
} }
// set i2c target // set i2c target
} else if (val == '0') { } else if (val == '0') {
i2c_dev = 0; i2c_dev = 0;
sendchar(val);
} else if (val >= '1' && val <= '4') { } else if (val >= '1' && val <= '4') {
i2c_dev = (val - '0' + TWI_ADDRESS_BASE) << 1; i2c_dev = (val - '0' + TWI_ADDRESS_BASE) << 1;
sendchar(val);
sendchar('<');
i2c_start_address(i2c_dev); i2c_switch_app(i2c_dev, BOOTTYPE_BOOTLOADER);
i2c_master_tx(CMD_SWITCH_APPLICATION); _delay_ms(100);
i2c_master_tx(BOOTTYPE_BOOTLOADER); i2c_print_version(i2c_dev);
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_start_address(i2c_dev); i2c_start_address(i2c_dev);
i2c_master_tx(CMD_READ_MEMORY); i2c_master_tx(CMD_READ_MEMORY);
@ -474,12 +405,7 @@ void cmd_loop(void)
uint8_t i; uint8_t i;
for (i = 0; i < sizeof(chipinfo); i++) { for (i = 0; i < sizeof(chipinfo); i++) {
uint8_t more = (i < (sizeof(chipinfo) -1)); uint8_t more = (i < (sizeof(chipinfo) -1));
i2c_master_rx(&chipinfo[i], more); chipinfo[i] = i2c_master_rx(more);
sendchar('0');
sendchar('x');
print_byte(chipinfo[i]);
sendchar(more ? ',' : '>');
} }
i2c_stop(); i2c_stop();
@ -489,39 +415,34 @@ void cmd_loop(void)
i2c_start_address(i2c_dev); i2c_start_address(i2c_dev);
i2c_master_tx(0x00 + (val - 'k') * 0x10); i2c_master_tx(0x00 + (val - 'k') * 0x10);
i2c_stop(); i2c_stop();
response = val;
sendchar(val);
} }
// start Application / get Version // get Version
} else if (val == 'I') { } else if (val == 'I') {
if (i2c_dev != 0) { if (i2c_dev != 0) {
i2c_start_address(i2c_dev); i2c_switch_app(i2c_dev, BOOTTYPE_APPLICATION);
i2c_master_tx(CMD_SWITCH_APPLICATION); _delay_ms(100);
i2c_master_tx(BOOTTYPE_APPLICATION); i2c_print_version(i2c_dev);
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();
} }
// fake MK-TOOL specific stuff
} else if (val == 0xAA) {
sendchar('M');
sendchar('K');
sendchar('B');
response = 'L';
/* ESC */ /* ESC */
} else if (val != 0x1b) { } 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. * system reset. So disable it as soon as possible.
* automagically called on startup * 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) __attribute__((naked, section(".init3")));
void disable_wdt_timer(void) void disable_wdt_timer(void)
{ {
@ -540,17 +460,15 @@ void disable_wdt_timer(void)
WDTCSR = (1<<WDCE) | (1<<WDE); WDTCSR = (1<<WDCE) | (1<<WDE);
WDTCSR = (0<<WDE); WDTCSR = (0<<WDE);
} }
#endif
/* linking without vectors, still need __vector_default */
void __vector_default(void) {}
int main(void) __attribute__ ((noreturn)); int main(void) __attribute__ ((noreturn));
int main(void) int main(void)
{ {
DDRB = LED_GN | LED_RT; DDRB = LED_GN | LED_RT;
PORTB = LED_GN | LED_RT; PORTB = LED_RT;
/* move interrupt-vectors to bootloader */
MCUCR = (1<<IVCE);
MCUCR = (1<<IVSEL);
/* Set baudrate */ /* Set baudrate */
UBRR0H = (UART_CALC_BAUDRATE(BAUDRATE)>>8) & 0xFF; UBRR0H = (UART_CALC_BAUDRATE(BAUDRATE)>>8) & 0xFF;
@ -560,35 +478,32 @@ int main(void)
UCSR0B = (1<<TXEN0) | (1<<RXEN0); UCSR0B = (1<<TXEN0) | (1<<RXEN0);
UCSR0C = (1<<UCSZ01) | (1<<UCSZ00); UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);
/* timer0: running with F_CPU/1024 */
TCCR0B = (1<<CS02) | (1<<CS00);
/* enable timer0 OVF interrupt */
TIMSK0 |= (1<<TOIE0);
/* enable TWI interface */ /* enable TWI interface */
TWBR = ((F_CPU/TWI_CLK)-16)/2; TWBR = ((F_CPU/TWI_CLK)-16)/2;
TWCR = (1<<TWSTO) | (1<<TWEN); TWCR = (1<<TWSTO) | (1<<TWEN);
sei(); uint8_t prev = 0x00;
uint8_t boot_timeout = 100;
while (boot_timeout > 0) { while (boot_timeout-- > 0) {
if (UCSR0A & (1<<RXC0)) if (UCSR0A & (1<<RXC0)) {
if (recvchar() == 'S') uint8_t val = recvchar();
cmd_loop();
if (prev == 0x1B && (val == 0xAA || val == 'S')) {
PORTB |= LED_GN;
cmd_loop(val);
boot_timeout = 0;
}
prev = val;
}
_delay_ms(10);
if (!(boot_timeout & 0x03))
PORTB ^= LED_GN;
} }
cli();
/* move interrupt-vectors to applicaion */
MCUCR = (1<<IVCE);
MCUCR = (0<<IVSEL);
PORTB = LED_RT; PORTB = LED_RT;
uint8_t i;
for (i = 0; i < 10; i++)
_delay_ms(10);
jump_to_app(); jump_to_app();
} }