|
|
|
@ -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<<PORTB0) /* low active */ |
|
|
|
|
#define LED_GN (1<<PORTB1) /* high active */ |
|
|
|
|
|
|
|
|
|
#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_SIGNATURE { 0x1E, 0x96, 0x0A } /* Mega644P */ |
|
|
|
|
|
|
|
|
@ -79,26 +79,14 @@ static uint8_t recvchar(void)
|
|
|
|
|
return UDR0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void print_byte(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) |
|
|
|
|
static void i2c_master_tx(uint8_t val) |
|
|
|
|
{ |
|
|
|
|
TWDR = val; |
|
|
|
|
TWCR = (1<<TWINT) | (1<<TWEN); |
|
|
|
|
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) |
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
loop_until_bit_is_set(TWCR, TWINT); |
|
|
|
|
*val = TWDR; |
|
|
|
|
|
|
|
|
|
uint8_t status = TWSR & 0xF8; |
|
|
|
|
return status; |
|
|
|
|
return TWDR; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void i2c_stop(void) |
|
|
|
@ -125,7 +110,8 @@ static void i2c_start_address(uint8_t addr)
|
|
|
|
|
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); |
|
|
|
|
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) |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
@ -134,66 +120,64 @@ static void i2c_start_address(uint8_t addr)
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* wait 100x 10ms */ |
|
|
|
|
volatile static uint8_t boot_timeout = 100; |
|
|
|
|
|
|
|
|
|
ISR(TIMER0_OVF_vect) |
|
|
|
|
static void i2c_switch_app(uint8_t i2c_dev, uint8_t app) |
|
|
|
|
{ |
|
|
|
|
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) */ |
|
|
|
|
TCNT0 = 0xFF - 195; |
|
|
|
|
_delay_ms(20); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
/* blink LED while running */ |
|
|
|
|
cnt++; |
|
|
|
|
cnt &= 0x03; |
|
|
|
|
if (cnt == 0x00) |
|
|
|
|
PORTB ^= LED_GN; |
|
|
|
|
uint8_t cnt = 16; |
|
|
|
|
while (cnt--) { |
|
|
|
|
sendchar(i2c_master_rx(cnt)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (boot_timeout > 0) |
|
|
|
|
boot_timeout--; |
|
|
|
|
i2c_stop(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static uint16_t address; |
|
|
|
|
static uint16_t page_size; |
|
|
|
|
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<<WDCE) | (1<<WDE); |
|
|
|
|
WDTCSR = (0<<WDE); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/* linking without vectors, still need __vector_default */ |
|
|
|
|
void __vector_default(void) {} |
|
|
|
|
|
|
|
|
|
int main(void) __attribute__ ((noreturn)); |
|
|
|
|
int main(void) |
|
|
|
|
{ |
|
|
|
|
DDRB = LED_GN | LED_RT; |
|
|
|
|
PORTB = LED_GN | LED_RT; |
|
|
|
|
|
|
|
|
|
/* move interrupt-vectors to bootloader */ |
|
|
|
|
MCUCR = (1<<IVCE); |
|
|
|
|
MCUCR = (1<<IVSEL); |
|
|
|
|
PORTB = LED_RT; |
|
|
|
|
|
|
|
|
|
/* Set baudrate */ |
|
|
|
|
UBRR0H = (UART_CALC_BAUDRATE(BAUDRATE)>>8) & 0xFF; |
|
|
|
@ -560,35 +478,32 @@ int main(void)
|
|
|
|
|
UCSR0B = (1<<TXEN0) | (1<<RXEN0); |
|
|
|
|
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 */ |
|
|
|
|
TWBR = ((F_CPU/TWI_CLK)-16)/2; |
|
|
|
|
TWCR = (1<<TWSTO) | (1<<TWEN); |
|
|
|
|
|
|
|
|
|
sei(); |
|
|
|
|
uint8_t prev = 0x00; |
|
|
|
|
uint8_t boot_timeout = 100; |
|
|
|
|
|
|
|
|
|
while (boot_timeout > 0) { |
|
|
|
|
if (UCSR0A & (1<<RXC0)) |
|
|
|
|
if (recvchar() == 'S') |
|
|
|
|
cmd_loop(); |
|
|
|
|
} |
|
|
|
|
while (boot_timeout-- > 0) { |
|
|
|
|
if (UCSR0A & (1<<RXC0)) { |
|
|
|
|
uint8_t val = recvchar(); |
|
|
|
|
|
|
|
|
|
cli(); |
|
|
|
|
if (prev == 0x1B && (val == 0xAA || val == 'S')) { |
|
|
|
|
PORTB |= LED_GN; |
|
|
|
|
cmd_loop(val); |
|
|
|
|
boot_timeout = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* move interrupt-vectors to applicaion */ |
|
|
|
|
MCUCR = (1<<IVCE); |
|
|
|
|
MCUCR = (0<<IVSEL); |
|
|
|
|
prev = val; |
|
|
|
|
} |
|
|
|
|
_delay_ms(10); |
|
|
|
|
|
|
|
|
|
PORTB = LED_RT; |
|
|
|
|
if (!(boot_timeout & 0x03)) |
|
|
|
|
PORTB ^= LED_GN; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint8_t i; |
|
|
|
|
for (i = 0; i < 10; i++) |
|
|
|
|
_delay_ms(10); |
|
|
|
|
PORTB = LED_RT; |
|
|
|
|
|
|
|
|
|
jump_to_app(); |
|
|
|
|
} |
|
|
|
|