1
0
mirror of https://github.com/Optiboot/optiboot.git synced 2025-08-19 09:02:05 +03:00

Two important discoveries:

1) Changing the watchdog period (inc turning it on) requires paying
   attention to synchonization between the WDT clock and system clock.
2) "jmp 512" doesn't work.  I'm not sure exactly what happens, but it doesn't go where I expected.

For now, do away with the fancy reset-cause logic and revert to old-style bootloader behavior.  Don't even do the no-wait mod; at least this permits you to enter the bootloader by power-cycle.

Implement LED_INVERT for boards that have the blink LED between +5V and pin.

Now working on ATtiny416 Xplained Mini!
This commit is contained in:
WestfW
2019-09-10 01:17:13 -07:00
parent adafe79832
commit ad0f55574a
3 changed files with 78 additions and 28 deletions

View File

@@ -251,19 +251,23 @@ COMMON_OPTIONS += $(VERSION_CMD)
#UART is handled separately and only passed for devices with more than one. #UART is handled separately and only passed for devices with more than one.
HELPTEXT += "Option UART=n - use UARTn for communications\n" HELPTEXT += "Option UART=n - use UARTn for communications\n"
HELPTEXT += "Option UARTTX=pin - describe UART for Mega0, Xtiny
ifdef UART ifdef UART
UART_CMD = -DUART=$(UART) UART_CMD = -DUART=$(UART)
endif endif
ifdef UARTTX
UART_CMD = -DUARTTX=$(UARTTX)
endif
# Not supported yet # Not supported yet
# ifdef TIMEOUT_MS # ifdef TIMEOUT
# TIMEOUT_MS_CMD = -DTIMEOUT_MS=$(TIMEOUT_MS) # TIMEOUT_CMD = -DTIMEOUT_MS=$(TIMEOUT)
# dummy = FORCE # dummy = FORCE
# endif # endif
# #
#.PRECIOUS: %.elf .PRECIOUS: %.elf
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# "Chip-level Platform" targets. # "Chip-level Platform" targets.

View File

@@ -135,3 +135,26 @@ luminet_isp: EFUSE ?= FE
luminet_isp: isp 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

View File

@@ -137,8 +137,10 @@ optiboot_version = 256*(OPTIBOOT_MAJVER + OPTIBOOT_CUSTOMVER) + OPTIBOOT_MINVER;
FUSES = { FUSES = {
.WDTCFG = 0, /* Watchdog Configuration */ .WDTCFG = 0, /* Watchdog Configuration */
.BODCFG = FUSE_BODCFG_DEFAULT, /* BOD Configuration */ .BODCFG = FUSE_BODCFG_DEFAULT, /* BOD Configuration */
.TCD0CFG = FUSE_TCD0CFG_DEFAULT, /* TCD0 Configuration */
.OSCCFG = 2, /* 20MHz */ .OSCCFG = 2, /* 20MHz */
#ifdef FUSE_TCD0CFG_DEFAULT
.TCD0CFG = FUSE_TCD0CFG_DEFAULT, /* TCD0 Configuration */
#endif
.SYSCFG0 = 0xC4, /* RESET is not yet */ .SYSCFG0 = 0xC4, /* RESET is not yet */
.SYSCFG1 = 0x06, /* startup 32ms */ .SYSCFG1 = 0x06, /* startup 32ms */
.APPEND = 0, /* Application Code Section End */ .APPEND = 0, /* Application Code Section End */
@@ -290,42 +292,51 @@ int main (void) {
// SP points to RAMEND // SP points to RAMEND
__asm__ __volatile__ ("clr __zero_reg__"); // known-zero required by avr-libc __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 * Protect as much Reset Cause as possible for application
* and still skip bootloader if not necessary * and still skip bootloader if not necessary
*/ */
ch = RSTCTRL.RSTFR; 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) { if (ch != 0) {
/* /*
* To run the boot loader, External Reset Flag must be set. * We want to run the bootloader when an external reset has occurred.
* If not, we could make shortcut and jump directly to application code. * On these mega0/XTiny chips, there are three types of ext reset:
* Also WDRF set with EXTRF is a result of Optiboot timeout, so we * reset pin (may not exist), UPDI reset, and SW-request reset.
* shouldn't run bootloader in loop :-) That's why: * One of these reset causes, together with watchdog reset, should
* 1. application is running if WDRF is cleared * mean that Optiboot timed out, and it's time to run the app.
* 2. we clear WDRF if it's set with EXTRF to avoid loops * Other reset causes (notably poweron) should run the app directly.
* One problematic scenario: broken application code sets watchdog timer * If a user app wants to utilize and detect watchdog resets, it
* without clearing MCUSR before and triggers it quickly. But it's * must make sure that the other reset causes are cleared.
* recoverable by power-on with pushed reset button.
*/ */
if ((ch & (RSTCTRL_WDRF_bm | RSTCTRL_EXTRF_bm)) != RSTCTRL_EXTRF_bm) { if (ch & RSTCTRL_WDRF_bm) {
if (ch & RSTCTRL_EXTRF_bm) { if (ch & RESET_EXTERNAL) {
/* /*
* Clear WDRF because it was most probably set by wdr in bootloader. * Clear WDRF because it was most probably set by wdr in
* It's also needed to avoid loop by broken application which could * bootloader. It's also needed to avoid loop by broken
* prevent entering bootloader. * application which could prevent entering bootloader.
* '&' operation is skipped to spare few bytes as bits in MCUSR
* can only be cleared.
*/ */
RSTCTRL.RSTFR = RSTCTRL_WDRF_bm; RSTCTRL.RSTFR = RSTCTRL_WDRF_bm;
} }
}
if (!(ch & RESET_EXTERNAL)) {
/* /*
* save the reset flags in the designated register * save the reset flags in the designated register.
* This can be saved in a main program by putting code in .init0 (which * This can be saved in a main program by putting code in
* executes before normal c init code) to save R2 to a global variable. * .init0 (which executes before normal c init code) to save R2
* to a global variable.
*/ */
__asm__ __volatile__ ("mov r2, %0\n" :: "r" (ch)); __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 _PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, 0); // full speed clock
MYUART_TXPORT.DIR |= MYUART_TXPIN; // set TX pin to output 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; MYUART.CTRLB = USART_RXEN_bm | USART_TXEN_bm;
// Set up watchdog to trigger after 1s // 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) #if (LED_START_FLASHES > 0) || defined(LED_DATA_FLASH) || defined(LED_START_ON)
/* Set LED pin as output */ /* Set LED pin as output */
@@ -360,11 +373,17 @@ int main (void) {
#if LED_START_FLASHES > 0 #if LED_START_FLASHES > 0
/* Flash onboard LED to signal entering of bootloader */ /* 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); flash_led(LED_START_FLASHES * 2);
# endif
#else #else
#if defined(LED_START_ON) #if defined(LED_START_ON)
# ifndef LED_INVERT
/* Turn on LED to indicate starting bootloader (less code!) */ /* Turn on LED to indicate starting bootloader (less code!) */
LED_PORT.OUT |= LED; LED_PORT.OUT |= LED;
# endif
#endif #endif
#endif #endif
@@ -405,7 +424,9 @@ int main (void) {
address.bytes[0] = getch(); address.bytes[0] = getch();
address.bytes[1] = getch(); address.bytes[1] = getch();
// ToDo: will there be mega-0 chips with >128k of RAM? // 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 address.word *= 2; // Convert from word address to byte address
*/
verifySpace(); verifySpace();
} }
else if(ch == STK_UNIVERSAL) { else if(ch == STK_UNIVERSAL) {
@@ -540,6 +561,8 @@ void flash_led (uint8_t count) {
#endif #endif
void watchdogConfig (uint8_t x) { void watchdogConfig (uint8_t x) {
while(WDT.STATUS & WDT_SYNCBUSY_bm)
;
_PROTECTED_WRITE(WDT.CTRLA, x); _PROTECTED_WRITE(WDT.CTRLA, x);
} }