complete
This commit is contained in:
parent
3f5a773ac7
commit
f311af0fca
2
Makefile
2
Makefile
@ -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
169
main.c
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user