This commit is contained in:
Olaf Rempel 2012-02-05 17:20:42 +01:00
parent 3f5a773ac7
commit f311af0fca
2 changed files with 88 additions and 83 deletions

View File

@ -9,7 +9,7 @@ BOOTLOADER_START=0x7800
AVRDUDE_MCU=m32 AVRDUDE_MCU=m32
endif endif
DEFS = -DBOOTLOADER_START=$(BOOTLOADER_START) DEFS = -DBOOTLOADER_START=$(BOOTLOADER_START) -DOSCCAL_VALUE=0xAA
LIBS = LIBS =
# Override is only needed by avr-lib build system. # Override is only needed by avr-lib build system.

169
main.c
View File

@ -42,17 +42,14 @@
/* 40 * 25ms */ /* 40 * 25ms */
#define TIMEOUT 40 #define TIMEOUT 40
#define LED_INIT() DDRD = (1<<PORTD3) | (1<<PORTD2) #define EN_TX (1<<PORTD2)
#define LED_RT_ON() /* not used */ #define LED_GN (1<<PORTD3)
#define LED_RT_OFF() /* not used */
#define LED_GN_ON() PORTD &= ~(1<<PORTD3)
#define LED_GN_OFF() PORTD |= (1<<PORTD3)
#define LED_GN_TOGGLE() PORTD ^= (1<<PORTD3)
#define LED_OFF() PORTD = (1<<PORTD3)
#define BAUDRATE 115200 #define BAUDRATE 115200
#define MPM_ADDRESS 0x11 #define MPM_ADDRESS 0x11
#define EEPROM_SUPPORT 1
#define CMD_WAIT 0x00 #define CMD_WAIT 0x00
#define CMD_SWITCH_MODE 0x01 #define CMD_SWITCH_MODE 0x01
#define CMD_GET_VERSION 0x02 #define CMD_GET_VERSION 0x02
@ -170,61 +167,59 @@ static uint8_t para_memtype;
static uint16_t para_address; static uint16_t para_address;
static uint16_t para_size; static uint16_t para_size;
/* flash buffer */ /* write buffer */
static uint8_t pagebuf[SPM_PAGESIZE]; static uint8_t pagebuf[SPM_PAGESIZE];
static void write_flash_page(void) static void write_flash_page(uint16_t pagestart, uint8_t *data, uint8_t size)
{ {
uint16_t pagestart = para_address; uint16_t address = pagestart;
uint8_t size = SPM_PAGESIZE; uint8_t pagesize = SPM_PAGESIZE;
uint8_t *p = pagebuf;
if (pagestart >= BOOTLOADER_START)
return;
boot_page_erase(pagestart); boot_page_erase(pagestart);
boot_spm_busy_wait(); boot_spm_busy_wait();
do { do {
uint16_t data = *p++; uint16_t dataword;
data |= *p++ << 8;
boot_page_fill(para_address, data);
para_address += 2; dataword = (size-- != 0) ? *data++ : 0xFF;
size -= 2; dataword |= ((size-- != 0) ? *data++ : 0xFF) << 8;
} while (size); boot_page_fill(address, dataword);
address += 2;
pagesize -= 2;
} while (pagesize);
boot_page_write(pagestart); boot_page_write(pagestart);
boot_spm_busy_wait(); boot_spm_busy_wait();
boot_rww_enable(); boot_rww_enable();
} }
static uint8_t read_eeprom_byte(void) #if (EEPROM_SUPPORT)
static uint8_t read_eeprom_byte(uint16_t address)
{ {
EEARL = para_address; EEARL = address;
EEARH = (para_address >> 8); EEARH = (address >> 8);
EECR |= (1<<EERE); EECR |= (1<<EERE);
return EEDR; return EEDR;
} }
static void write_eeprom_page(void) static void write_eeprom_page(uint16_t address, uint8_t *data, uint16_t size)
{ {
uint8_t *val = pagebuf; while (size--) {
while (para_size) { EEARL = address;
EEARL = para_address; EEARH = (address >> 8);
EEARH = (para_address >> 8); address++;
EEDR = *val++; EEDR = *data++;
para_address++;
para_size--;
#if defined (__AVR_ATmega32__) #if defined (__AVR_ATmega32__)
EECR |= (1<<EEMWE); EECR |= (1<<EEMWE);
EECR |= (1<<EEWE); EECR |= (1<<EEWE);
#else #else
#error write_eeprom_byte(): access not defined #error write_eeprom_page(): access not defined
#endif #endif
eeprom_busy_wait(); eeprom_busy_wait();
} }
} }
#endif /* (EEPROM_SUPPORT) */
ISR(USART_RXC_vect) ISR(USART_RXC_vect)
{ {
@ -234,7 +229,8 @@ ISR(USART_RXC_vect)
/* own address, disable MPM mode and receive following bytes */ /* own address, disable MPM mode and receive following bytes */
if (data == MPM_ADDRESS) { if (data == MPM_ADDRESS) {
boot_wait = BOOTWAIT_INTERRUPTED; boot_wait = BOOTWAIT_INTERRUPTED;
LED_GN_ON(); /* enable LED */
PORTD &= ~(LED_GN);
UCSRA &= ~(1<<MPCM); UCSRA &= ~(1<<MPCM);
rx_addressed = 1; rx_addressed = 1;
@ -242,44 +238,49 @@ ISR(USART_RXC_vect)
} }
} else { } else {
/* byte 0 is command */
if (rx_bcnt == 0) { if (rx_bcnt == 0) {
rx_cmd = data; rx_cmd = data;
/* byte 1/2 is payload length */
} else if (rx_bcnt == 1 || rx_bcnt == 2) { } else if (rx_bcnt == 1 || rx_bcnt == 2) {
rx_length = (rx_length << 8) | data; rx_length = (rx_length << 8) | data;
} else if ((rx_cmd == CMD_SWITCH_MODE) && (rx_bcnt == 3)) { /* byte >= 3 is payload */
para_mode = data; } else if ((rx_bcnt -3) < rx_length) {
uint16_t pos = rx_bcnt -3;
} else if (((rx_cmd == CMD_READ_MEMORY) || (rx_cmd == CMD_WRITE_MEMORY)) && if ((rx_cmd == CMD_SWITCH_MODE) && (pos == 0)) {
((rx_bcnt >= 3) && (rx_bcnt <= 7)) para_mode = data;
) {
switch (rx_bcnt) {
case 3:
para_memtype = data;
break;
case 4: } else if ((rx_cmd == CMD_READ_MEMORY) || (rx_cmd == CMD_WRITE_MEMORY)) {
case 5: switch (pos) {
para_address = (para_address << 8) | data; case 0:
break; para_memtype = data;
break;
case 6: case 1:
case 7: case 2:
para_size = (para_size << 8) | data; para_address = (para_address << 8) | data;
break; break;
default: case 3:
break; case 4:
} para_size = (para_size << 8) | data;
break;
} else if ((rx_cmd == CMD_WRITE_MEMORY) && (rx_bcnt > 7) && (rx_bcnt <= (rx_length +2))) { default:
if ((rx_bcnt -8) < sizeof(pagebuf)) { pos -= 5;
pagebuf[(rx_bcnt -8)] = data; if ((rx_cmd == CMD_WRITE_MEMORY) && (pos < sizeof(pagebuf))) {
pagebuf[pos] = data;
}
break;
}
} }
} }
if (rx_bcnt == (rx_length +2)) { /* last byte received */
if ((rx_bcnt -2) == rx_length) {
/* setup response */ /* setup response */
tx_bcnt = 0; tx_bcnt = 0;
tx_cmd = rx_cmd; tx_cmd = rx_cmd;
@ -311,24 +312,28 @@ ISR(USART_RXC_vect)
tx_length = 0; tx_length = 0;
tx_cause = CAUSE_INVALID_PARAMETER; tx_cause = CAUSE_INVALID_PARAMETER;
/* writes must use pagesize */ /* writes must pagesize aligned */
} else if (tx_cmd == CMD_WRITE_MEMORY) { } else if (tx_cmd == CMD_WRITE_MEMORY) {
if (para_size == SPM_PAGESIZE) { if (((para_address & (SPM_PAGESIZE -1)) == 0x00) &&
write_flash_page(); (para_size <= SPM_PAGESIZE)
) {
write_flash_page(para_address, pagebuf, para_size);
para_address += para_size;
} else { } else {
tx_cause = CAUSE_INVALID_PARAMETER; tx_cause = CAUSE_INVALID_PARAMETER;
} }
} }
#if (EEPROM_SUPPORT)
} else if (para_memtype == MEMTYPE_EEPROM) { } else if (para_memtype == MEMTYPE_EEPROM) {
if ((para_address > (E2END +1)) || ((para_address + para_size) > (E2END +1))) { if ((para_address > (E2END +1)) || ((para_address + para_size) > (E2END +1))) {
tx_cause = CAUSE_INVALID_PARAMETER; tx_cause = CAUSE_INVALID_PARAMETER;
} else if (tx_cmd == CMD_WRITE_MEMORY) { } else if (tx_cmd == CMD_WRITE_MEMORY) {
write_eeprom_page(); write_eeprom_page(para_address, pagebuf, para_size);
para_address += para_size;
} }
#endif /*(EEPROM_SUPPORT) */
} else { } else {
tx_length = 0; tx_length = 0;
tx_cause = CAUSE_INVALID_PARAMETER; tx_cause = CAUSE_INVALID_PARAMETER;
@ -352,7 +357,8 @@ ISR(USART_UDRE_vect)
{ {
if (tx_bcnt == 0) { if (tx_bcnt == 0) {
/* enable RS485 transmitter */ /* enable RS485 transmitter */
PORTD |= (1<<PORTD2); PORTD |= EN_TX;
UCSRB &= ~(1<<TXB8); UCSRB &= ~(1<<TXB8);
UDR = tx_cmd; UDR = tx_cmd;
@ -365,7 +371,7 @@ ISR(USART_UDRE_vect)
} else if (tx_bcnt == 3) { } else if (tx_bcnt == 3) {
UDR = (tx_length & 0xFF); UDR = (tx_length & 0xFF);
} else if (tx_bcnt < (tx_length +4)) { } else if ((tx_bcnt -4) < tx_length) {
uint16_t pos = tx_bcnt -4; uint16_t pos = tx_bcnt -4;
uint8_t data = 0xFF; uint8_t data = 0xFF;
@ -377,12 +383,11 @@ ISR(USART_UDRE_vect)
} else if (tx_cmd == CMD_READ_MEMORY) { } else if (tx_cmd == CMD_READ_MEMORY) {
if (para_memtype == MEMTYPE_FLASH) { if (para_memtype == MEMTYPE_FLASH) {
data = pgm_read_byte_near(para_address); data = pgm_read_byte_near(para_address++);
para_address++; #if (EEPROM_SUPPORT)
} else if (para_memtype == MEMTYPE_EEPROM) { } else if (para_memtype == MEMTYPE_EEPROM) {
data = read_eeprom_byte(); data = read_eeprom_byte(para_address++);
para_address++; #endif /* (EEPROM_SUPPORT) */
} }
} }
@ -398,17 +403,18 @@ ISR(USART_UDRE_vect)
ISR(USART_TXC_vect) ISR(USART_TXC_vect)
{ {
LED_GN_OFF(); /* disable LED */
PORTD |= LED_GN;
/* disable RS485 transmitter */ /* disable RS485 transmitter */
PORTD &= ~(1<<PORTD2); PORTD &= ~(EN_TX);
/* enable MP mode again */ /* enable MP mode again */
UCSRA |= (1<<MPCM); UCSRA |= (1<<MPCM);
rx_addressed = 0; rx_addressed = 0;
/* switch to application after everything is transmitted */ /* switch to application after everything is transmitted */
if (tx_cmd == CMD_SWITCH_MODE) { if ((tx_cmd == CMD_SWITCH_MODE) && (para_mode == BOOTMODE_APPLICATION)) {
boot_wait = BOOTWAIT_EXPIRED; boot_wait = BOOTWAIT_EXPIRED;
} }
} }
@ -419,7 +425,7 @@ ISR(TIMER0_OVF_vect)
TCNT0 = TIMER_RELOAD; TCNT0 = TIMER_RELOAD;
if (boot_wait == BOOTWAIT_RUNNING) { if (boot_wait == BOOTWAIT_RUNNING) {
LED_GN_TOGGLE(); PORTD ^= LED_GN;
boot_timeout--; boot_timeout--;
if (boot_timeout == 0) { if (boot_timeout == 0) {
@ -443,13 +449,11 @@ static void (*jump_to_app)(void) __attribute__ ((noreturn)) = 0x0000;
int main(void) __attribute__ ((noreturn)); int main(void) __attribute__ ((noreturn));
int main(void) int main(void)
{ {
LED_INIT(); /* LED and TXEN are outputs */
LED_GN_OFF(); DDRD |= LED_GN | EN_TX;
#if (BAUDRATE == 115200) #if defined(OSCCAL_VALUE)
OSCCAL = 0xAA; OSCCAL = OSCCAL_VALUE;
#elif (BAUDRATE == 9600)
OSCCAL = 0xB8;
#endif #endif
/* move interrupt-vectors to bootloader */ /* move interrupt-vectors to bootloader */
@ -490,7 +494,8 @@ int main(void)
GICR = (0<<IVSEL); GICR = (0<<IVSEL);
#endif #endif
LED_OFF(); /* disable LED */
PORTD |= LED_GN;
uint16_t wait = 0x0000; uint16_t wait = 0x0000;
do { do {