diff --git a/optiboot/bootloaders/optiboot/Makefile b/optiboot/bootloaders/optiboot/Makefile index 3f923a8..b28461b 100644 --- a/optiboot/bootloaders/optiboot/Makefile +++ b/optiboot/bootloaders/optiboot/Makefile @@ -251,19 +251,23 @@ COMMON_OPTIONS += $(VERSION_CMD) #UART is handled separately and only passed for devices with more than one. HELPTEXT += "Option UART=n - use UARTn for communications\n" +HELPTEXT += "Option UARTTX=pin - describe UART for Mega0, Xtiny ifdef UART UART_CMD = -DUART=$(UART) endif +ifdef UARTTX +UART_CMD = -DUARTTX=$(UARTTX) +endif # Not supported yet -# ifdef TIMEOUT_MS -# TIMEOUT_MS_CMD = -DTIMEOUT_MS=$(TIMEOUT_MS) +# ifdef TIMEOUT +# TIMEOUT_CMD = -DTIMEOUT_MS=$(TIMEOUT) # dummy = FORCE # endif # -#.PRECIOUS: %.elf +.PRECIOUS: %.elf #--------------------------------------------------------------------------- # "Chip-level Platform" targets. diff --git a/optiboot/bootloaders/optiboot/Makefile.extras b/optiboot/bootloaders/optiboot/Makefile.extras index 0bb403c..b166264 100644 --- a/optiboot/bootloaders/optiboot/Makefile.extras +++ b/optiboot/bootloaders/optiboot/Makefile.extras @@ -135,3 +135,26 @@ luminet_isp: EFUSE ?= FE luminet_isp: isp +HELPTEXT += "target atmega4809 - ATmega4809\n" +atmega4809: TARGET = atmega4809 +atmega4809: PROGRAM = optiboot_x +atmega4809: MCU_TARGET = atmega4809 +atmega4809: CFLAGS += $(COMMON_OPTIONS) -DLED=A7 $(UART_CMD) +atmega4809: AVR_FREQ ?= 20000000L +atmega4809: LDSECTIONS = -Wl,--section-start=.text=0 -Wl,--section-start=.version=0x1fe -Wl,--sections-start=.postapp=0x200 +atmega4809: $(PROGRAM)_atmega4809.hex +ifndef PRODUCTION +atmega4809: $(PROGRAM)_atmega4809.lst +endif + +HELPTEXT += "target Xplained416 - ATtiny416 Xplained Nano\n" +xplained416: TARGET = attiny416 +xplained416: PROGRAM = optiboot_x +xplained416: MCU_TARGET = attiny416 +xplained416: CFLAGS += $(COMMON_OPTIONS) $(UART_CMD) -DLED_INVERT=1 +xplained416: AVR_FREQ ?= 20000000L +xplained416: LDSECTIONS = -Wl,--section-start=.text=0 -Wl,--section-start=.version=0x1fe -Wl,--section-start=.postapp=0x200 +xplained416: $(PROGRAM)_attiny416.hex +ifndef PRODUCTION +xplained416: $(PROGRAM)_attiny416.lst +endif diff --git a/optiboot/bootloaders/optiboot/optiboot_x.c b/optiboot/bootloaders/optiboot/optiboot_x.c index f882de5..2aece06 100644 --- a/optiboot/bootloaders/optiboot/optiboot_x.c +++ b/optiboot/bootloaders/optiboot/optiboot_x.c @@ -137,8 +137,10 @@ optiboot_version = 256*(OPTIBOOT_MAJVER + OPTIBOOT_CUSTOMVER) + OPTIBOOT_MINVER; FUSES = { .WDTCFG = 0, /* Watchdog Configuration */ .BODCFG = FUSE_BODCFG_DEFAULT, /* BOD Configuration */ - .TCD0CFG = FUSE_TCD0CFG_DEFAULT, /* TCD0 Configuration */ .OSCCFG = 2, /* 20MHz */ +#ifdef FUSE_TCD0CFG_DEFAULT + .TCD0CFG = FUSE_TCD0CFG_DEFAULT, /* TCD0 Configuration */ +#endif .SYSCFG0 = 0xC4, /* RESET is not yet */ .SYSCFG1 = 0x06, /* startup 32ms */ .APPEND = 0, /* Application Code Section End */ @@ -290,42 +292,51 @@ int main (void) { // SP points to RAMEND __asm__ __volatile__ ("clr __zero_reg__"); // known-zero required by avr-libc - +#define RESET_EXTERNAL (RSTCTRL_EXTRF_bm|RSTCTRL_UPDIRF_bm|RSTCTRL_SWRF_bm) +#ifndef FANCY_RESET_LOGIC + ch = RSTCTRL.RSTFR; // get reset cause + RSTCTRL.RSTFR = ch; // and reset them all! + if (ch & RSTCTRL_WDRF_bm) { + // Start the app. + __asm__ __volatile__ ("mov r2, %0\n" :: "r" (ch)); + watchdogConfig(WDT_PERIOD_OFF_gc); + __asm__ __volatile__ ( + "jmp app\n" + ); + } +#else /* * Protect as much Reset Cause as possible for application * and still skip bootloader if not necessary */ ch = RSTCTRL.RSTFR; -// RSTCTRL.RSTFR = ch; // reset causes, for now. - ch &= ~RSTCTRL_UPDIRF_bm; // clear "reset by UPDI." - // Skip all logic and run bootloader if cause is cleared (application request) if (ch != 0) { /* - * To run the boot loader, External Reset Flag must be set. - * If not, we could make shortcut and jump directly to application code. - * Also WDRF set with EXTRF is a result of Optiboot timeout, so we - * shouldn't run bootloader in loop :-) That's why: - * 1. application is running if WDRF is cleared - * 2. we clear WDRF if it's set with EXTRF to avoid loops - * One problematic scenario: broken application code sets watchdog timer - * without clearing MCUSR before and triggers it quickly. But it's - * recoverable by power-on with pushed reset button. + * We want to run the bootloader when an external reset has occurred. + * On these mega0/XTiny chips, there are three types of ext reset: + * reset pin (may not exist), UPDI reset, and SW-request reset. + * One of these reset causes, together with watchdog reset, should + * mean that Optiboot timed out, and it's time to run the app. + * Other reset causes (notably poweron) should run the app directly. + * If a user app wants to utilize and detect watchdog resets, it + * must make sure that the other reset causes are cleared. */ - if ((ch & (RSTCTRL_WDRF_bm | RSTCTRL_EXTRF_bm)) != RSTCTRL_EXTRF_bm) { - if (ch & RSTCTRL_EXTRF_bm) { + if (ch & RSTCTRL_WDRF_bm) { + if (ch & RESET_EXTERNAL) { /* - * Clear WDRF because it was most probably set by wdr in bootloader. - * It's also needed to avoid loop by broken application which could - * prevent entering bootloader. - * '&' operation is skipped to spare few bytes as bits in MCUSR - * can only be cleared. + * Clear WDRF because it was most probably set by wdr in + * bootloader. It's also needed to avoid loop by broken + * application which could prevent entering bootloader. */ RSTCTRL.RSTFR = RSTCTRL_WDRF_bm; } + } + if (!(ch & RESET_EXTERNAL)) { /* - * save the reset flags in the designated register - * This can be saved in a main program by putting code in .init0 (which - * executes before normal c init code) to save R2 to a global variable. + * save the reset flags in the designated register. + * This can be saved in a main program by putting code in + * .init0 (which executes before normal c init code) to save R2 + * to a global variable. */ __asm__ __volatile__ ("mov r2, %0\n" :: "r" (ch)); @@ -336,7 +347,9 @@ int main (void) { ); } } +#endif // Fancy reset cause stuff + watchdogReset(); _PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, 0); // full speed clock MYUART_TXPORT.DIR |= MYUART_TXPIN; // set TX pin to output @@ -351,7 +364,7 @@ int main (void) { MYUART.CTRLB = USART_RXEN_bm | USART_TXEN_bm; // Set up watchdog to trigger after 1s - watchdogConfig(WDT_PERIOD_1KCLK_gc); + watchdogConfig(WDT_PERIOD_8KCLK_gc); #if (LED_START_FLASHES > 0) || defined(LED_DATA_FLASH) || defined(LED_START_ON) /* Set LED pin as output */ @@ -360,11 +373,17 @@ int main (void) { #if LED_START_FLASHES > 0 /* Flash onboard LED to signal entering of bootloader */ +# ifdef LED_INVERT + flash_led(LED_START_FLASHES * 2+1); +# else flash_led(LED_START_FLASHES * 2); +# endif #else #if defined(LED_START_ON) +# ifndef LED_INVERT /* Turn on LED to indicate starting bootloader (less code!) */ LED_PORT.OUT |= LED; +# endif #endif #endif @@ -405,7 +424,9 @@ int main (void) { address.bytes[0] = getch(); address.bytes[1] = getch(); // ToDo: will there be mega-0 chips with >128k of RAM? +/* UPDI chips apparently have byte-addressable FLASH ? address.word *= 2; // Convert from word address to byte address +*/ verifySpace(); } else if(ch == STK_UNIVERSAL) { @@ -540,6 +561,8 @@ void flash_led (uint8_t count) { #endif void watchdogConfig (uint8_t x) { + while(WDT.STATUS & WDT_SYNCBUSY_bm) + ; _PROTECTED_WRITE(WDT.CTRLA, x); }